Back to Interview Prep

Interview · Lesson 2

System Design for Rails Interviews

Most senior Rails roles have one system-design round. It looks open-ended; it isn't. Interviewers are scoring on five specific things.

The frame interviewers use

Most senior Rails system-design rounds score on the same five axes. Knowing the axes is half the battle.

  1. Requirements clarification. Did you ask what scale, what reads vs writes, what consistency model, what's in scope vs out.
  2. Data model. What tables, what relationships, what indexes, what to denormalize and why.
  3. Request lifecycle. What happens end-to-end when a user does the thing. Where the work happens (synchronous vs background), where the bottlenecks are.
  4. Trade-offs named. Every design choice has a cost. Did you name it without being asked.
  5. Failure modes. What happens when the cache is down, when the queue backs up, when the database is at 95% CPU, when a retry happens.

The common prompts (and what they're really testing)

  • "Design a URL shortener." Testing: do you know about ID generation strategies (auto-increment vs base62-encoded UUID vs hash), read-heavy caching, and what a write-amplification looks like.
  • "Design a notification system." Testing: synchronous vs async dispatch, fan-out (in-memory vs database vs queue-per-user), at-least-once vs exactly-once delivery, deduplication.
  • "Design a rate limiter." Testing: token bucket vs sliding window vs fixed window, where state lives (Redis vs database), what happens when the rate-limit store is down (fail open vs fail closed).
  • "Design a multi-tenant SaaS." Testing: row-level vs schema-level isolation, how authorization is scoped, how migrations work across tenants, how billing is modeled.
  • "Design X for Rails specifically." Testing: do you reach for the framework's idioms (ActiveJob, ActiveRecord, Hotwire) or treat Rails like a generic web framework. The former scores higher.

The structure that works

# 5 min: clarify requirements
#   "Reads: how many per second? Writes? Latency target?"
#   "What's in scope? Auth? Analytics? Multi-region?"
#   "How long does the system have to live? Hours? Years?"
#
# 5 min: data model
#   Draw the tables. Name the indexes. Call out denormalizations.
#   "users(id), short_urls(id, code, target_url, user_id),
#    clicks(id, short_url_id, ip, timestamp)"
#
# 10 min: request lifecycle
#   GET /a1b2: hot path. Redis cache by code → target_url.
#   Cache miss: DB lookup, populate cache. Async-record the click.
#   POST /shorten: generate code, INSERT, return.
#
# 5 min: trade-offs and failure modes
#   "If Redis is down, fall back to DB. Slower but correct."
#   "If the click-recorder queue backs up, we lose analytics but
#    not redirects. That's the right priority."
#   "At 100x scale, the bottleneck moves to the DB. Read replicas
#    next, then maybe a NoSQL store for clicks specifically."

Trade-offs that come up over and over

  • Synchronous vs background job. "The user doesn't need to see this complete" goes to a job.
  • Cache vs query every time. Read-heavy data with tolerable staleness goes to cache. Show you know about cache stampede and TTL jitter.
  • Strong vs eventual consistency. Money strong, analytics eventual.
  • Database vs Redis vs S3. Right tool for the shape. Don't store images in the database. Don't store transactions in Redis without a durable backup.
  • Vertical vs horizontal scale. Bigger box vs more boxes. Bigger box wins until ~50K req/min for most Rails apps; after that, you start sharding.