Day 94 of 100·Project Deep-Dive Day·674 words

Traverse rapid-fire + the RabbitMQ claim, handled

25 questions on your own product, plus the exact script for the resume discrepancy.

Know your own system

The drill set, then the script.

  1. What is Traverse? → passive DSA capture (extension) + spaced-repetition scheduling + streaks/analytics, iOS app + backend.
  2. How does capture work? → MAIN-world network interception in the extension; platform adapters normalize judge responses; POST with idempotency key + device id.
  3. Why a queue? → 15 s LLM ladder off the request path; 10 s → 0.2 s p95 (Day 4).
  4. Which queue, precisely? → BullMQ on Redis. (And the resume script — see below.)
  5. How do you dedup submissions? → @@unique([userId, idempotencyKey]); duplicate POST returns 200 with the existing row.
  6. What happens on the AI provider failing? → ladder falls through (BYOK Gemini → server Gemini → Groq → G4F), JSON cleaned/validated, heuristic fallback, scheduling never blocks on AI.
  7. How does scheduling work? → FSRS-style memory state per problem/user-topic; due dates from retrievability targets (0.85); predictions persisted with model version; calibration measured.
  8. What's the calibration harness? → predicted vs observed, bucketed by modelVersion (Day 72).
  9. Free vs premium? → AI signals nulled at one choke point for free users; the deterministic scheduler path is always exercised.
  10. How do notifications work? → intent (Notification) + per-channel ledger (NotificationDelivery) with lease claim, backoff, terminal statuses; push best-effort via APNs/FCM; in-app truth.
  11. Why no WebSockets? → push for closed apps, polling for freshness, no stateful socket fleet (Day 73).
  12. Cache strategy? → cache-aside, per-data TTLs (120–600 s), worker-driven invalidation, 2 s timeouts, degrade-to-no-op.
  13. Redis policies? → noeviction (queue safety over cache elasticity), AOF, removeOnComplete bounds (Day 46).
  14. What breaks at 2 replicas? → in-memory rate limiters and node-cron jobs (Day 50).
  15. Biggest query perf win? → streak walk 300→2 queries; achievements 120→4 (Day 28).
  16. Durability? → WAL archiving to S3, 5-min RPO, Aiven offsite, executable restore endpoints (Day 34).
  17. Deploy? → GitLab CI → SSH → compose, git-reset + rebuild + health gate, migrate-on-boot refusing stale schemas.
  18. Security posture? → bcrypt-12, strict auth limits, webhook HMAC over raw body, log redaction, BYOK isolation; debts: hardcoded provider key, two timing-unsafe compares (Day 90).
  19. How do you know it works? → integration tests replaying real migrations, per-feature regression tests (the wiring bugs I found and guarded), calibration for the scheduler.
  20. Social graph? → double-row friendship, canonical pair streaks with CHECK constraint, blocks filtered by a single visibility predicate.
  21. What's the recon feature? → streaming unbounded capture dumps to disk, .partial + atomic rename, per-platform quota, digest email (Day 82).
  22. Biggest scaling limit? → single VPS, single Redis, in-memory limiters; the ladder is Redis-backed limits → read replicas → partition submissions.
  23. What would you rebuild? → submission outbox (close the enqueue gap), Redis split, token expiry on JWTs, encrypted BYOK keys.
  24. Why Node/TypeScript? → one language across extension, backend, tooling; the workload is I/O-bound, not CPU-bound.
  25. What are you proudest of? → the fact/derivation split that made a 50× latency win safe, and the calibration harness that measures the scheduler instead of asserting it works.

The RabbitMQ script (memorize verbatim)

If asked "your resume says RabbitMQ for Traverse":

"My resume summarizes the pattern as a message queue — the implementation is BullMQ over Redis, and RabbitMQ is the technology in my other project, Zoth. The architectural decision is identical in both: decouple ingestion from downstream processing so user-facing writes don't pay for slow side effects. In Traverse I chose a Redis-backed queue because the jobs are small triggers whose truth lives in Postgres, and a single VPS didn't need a second broker; in Zoth I chose RabbitMQ because provisioning events needed broker-native retry accounting, DLQ semantics, and process isolation — and I can go deep on either."

Then pivot to what you did build (the 50× win), not to the discrepancy. Own it, don't litigate it.

Bulletproof your resume

Say these answers aloud before moving on

These are the follow-ups an interviewer will actually ask about your projects.

01

You're asked to compare BullMQ and RabbitMQ — answer from experience.

BullMQ: Redis-backed, jobs as Redis structures, delayed/repeatable jobs, per-queue concurrency and rate limits, jobId-based dedup, stalled-job recovery, AOF for restart durability; ops cost is one Redis you already run. RabbitMQ: real broker semantics — exchanges and routing keys, prefetch-based credit flow control, per-message ack/nack, x-death retry accounting, dead-letter exchanges, and language-agnostic clients; ops cost is a broker to run. I've shipped both: BullMQ for the product pipeline where the DB holds truth and jobs are triggers; RabbitMQ where provisioning events needed DLQ/retry semantics and process isolation from request handling.

02

What's the strongest technical story in Traverse?

The fact/derivation split and its measured consequence: submissions and solves are durable facts written synchronously; revisions, streaks, rings, achievements, and notifications are derivations computed by workers from those facts. That let me move the entire AI ladder (15 s timeouts, multiple providers) off the request path for a 50× p95 improvement without weakening durability — and it also means derived state is rebuildable, which is why Redis losing a job degrades features instead of corrupting truth. The calibration harness is the same philosophy applied to the algorithm: measure rather than assert.

03

What's the weakest part of your answer set?

Anything about the client side — the extension's interception details and the iOS app are the parts I've spent least time in recently, and an interviewer who probes MAIN-world vs isolated-world interception or SwiftUI state management could go deeper than I can answer fluently today. That's on my study list, and it's an honest boundary rather than a bluff: I'd rather say 'that's the layer I know least' than invent details about code I didn't write.