Key technology building blocks for system design

Key technologies

One problem, one failure mode, one 'don't use this for' — per tool. Postgres, DynamoDB, S3, Elasticsearch, queues, streams, distributed locks, Redis, and CDNs, run through a single film-crew analogy so the roles stay distinct.

Why key technologies matter

Interviews reward a small, well-justified toolbox over a large, name-dropped one. Nobody cares if you pick Kafka or SQS — only that you have a queue you can reason about under pressure. The real failure mode is not knowing any queueing solution at all: async workloads become impossible to design, not just suboptimal.

Analogy diagram: film crew roles mapped to databases, S3, queues, Redis, CDN.
One go-to name per crew role — camera, warehouse, runner, prompt, screens.

The categories below cover roughly 90% of interview problems. Pick within each category however you like — but show up with at least one name you actually know well.

  • Core database (Postgres or DynamoDB)
  • Blob storage (S3)
  • Search database (Elasticsearch)
  • API gateway · Load balancer
  • Queue · Streams
  • Distributed lock · Distributed cache · CDN

Already know the concepts? Start with Core concepts overview for the theory layer beneath these tools.

Core database

Almost every design stores data in a database or blob storage. The two real choices are relational (Postgres) and NoSQL (DynamoDB) — pick by the shape of the interview more than the specific problem.

  • Mostly product design interviews → default to Postgres.
  • Mostly infrastructure interviews → default to DynamoDB.

Good opener: "I'm using Postgres here because ACID transactions keep order and inventory consistent." If you're pushed to compare, compare databases you actually know — and say how each one would change the design, not which one wins in the abstract.

Relational databases (Postgres)

Reach for Postgres or MySQL when the data is transactional and the relationships matter: users, orders, bookings. Rows and columns, queried with SQL.

  • Joins combine tables — clean at low volume, and the first thing to bottleneck once a table crosses a few million rows. Denormalize or cache before you consider a full migration.
  • Indexes (B-tree, hash, multi-column, geospatial, full-text) are the actual scaling lever — build them for the query pattern, not the schema.
  • Transactions make multi-row writes atomic: reserve seat, create payment intent, decrement inventory — all succeed or all roll back, never half.

Don't reach for Postgres when your access pattern is one huge table, always queried by a single key, at extreme write volume — that's a NoSQL problem, not a tuning problem. Otherwise: pick Postgres or MySQL. No preference? Postgres — every interviewer has an opinion about it, which works in your favor.

NoSQL databases (DynamoDB)

NoSQL covers key-value, document, column-family, and graph stores — schema-flexible, built for horizontal write scale.

NoSQL database types: key-value, document, column-family, and graph stores.
NoSQL families — pick the model that matches your access pattern.
  • Data shapes evolve without a rigid schema to migrate.
  • Horizontal scale across many servers for huge volume or traffic.
  • Big data, real-time analytics, unstructured payloads.
  • Data models — key-value, document, column-family, graph.
  • Consistency — strong to eventual; pick per use case.
  • Indexing — B-tree, hash, like relational but designed around access patterns.
  • Scale — consistent hashing + sharding across nodes.

Common picks: DynamoDB (breadth, interview familiarity), Cassandra (write-heavy, append-only, fewer query guarantees in trade), MongoDB (document store). Failure mode: the moment your access pattern needs an ad-hoc query you didn't design a GSI for, latency and cost both spike. Constantly inventing new query shapes is the signal you actually wanted Postgres.

Blob storage (S3)

Images, videos, PDFs don't belong in Postgres or DynamoDB rows. Push them to S3, GCS, or Azure Blob — cheap, durable, and effectively infinite for interview purposes.

Pattern: DB stores pointers (URLs); blob store holds bytes. Query and index in the DB; serve bytes from S3 + CDN.

Client, server, S3 blob storage, CDN, and core database with presigned uploads.
Basic blob storage setup — metadata in DB, bytes in S3, served via CDN.

Upload flow (presigned URLs):

  1. Client asks server for presigned upload URL.
  2. Server returns URL + records pending upload in DB.
  3. Client uploads directly to S3.
  4. S3 notifies server; status → complete.

Download: server returns a presigned URL, client fetches via CDN, CDN proxies to S3 origin on a miss.

  • Durability — replication, erasure coding.
  • Cost — ~$0.023/GB/mo (S3) vs ~$1.25/GB/mo (DynamoDB) for the same data. That gap alone should keep large blobs out of your database.
  • Presigned URLs — temporary upload/download access without exposing credentials.
  • Multipart upload — chunk large files, resume on failure instead of restarting from zero.

Search-optimized database

WHERE text LIKE '%term%' scans every row — dies at scale. Search engines use inverted indexes instead: word → list of documents.

{
  "word1": [doc1, doc2, doc3],
  "word2": [doc2, doc3, doc4]
}

Look up the query token, get an instant candidate document list. Fast because you never touch the rows that don't match.

  • Tokenization — split text into words.
  • Stemming — "running" and "runs" both index as "run".
  • Fuzzy search — tolerate typos via edit distance.
  • Scale — cluster + sharding, like other DBs.

Leader: Elasticsearch (Lucene underneath). Don't stand up a whole Elasticsearch cluster for a search box hitting under ~10k rows — Postgres GIN full-text covers that without a second system to operate and page on. Reach for Redis search only for small, latency-critical lookups; it's not mature enough yet for heavy search workloads.

API gateway

In microservices — and most product designs — an API gateway is the front door: route GET /users/123 to the users service, handle auth, rate limits, logging, all before any business logic runs.

Client sending requests through an API gateway to three microservices.
API gateway — one entry point routing to the right microservice.

Interviewers rarely deep-dive gateway internals: draw the box, name the cross-cutting concerns, move on. Don't bother drawing one for a single-service toy design — a gateway earns its place once you actually have more than one service behind it.

Common options: AWS API Gateway, Kong, Apigee, or plain nginx/Apache, the way early Amazon did it.

Load balancer

Every box on your whiteboard should earn its place with a reason.

High traffic means spreading requests across machines. For most interviews, the load balancer is a black box that distributes work — you rarely need to go deeper than that.

Client to API gateway to load balancer to service — horizontally scaled authenticated setup.
Common setup — gateway for auth, load balancer for horizontal scale.
  • L7 (application) — routes by HTTP path/content; flexible.
  • L4 (TCP) — faster, dumber; use for WebSockets and other persistent connections.
  • Rule of thumb: WebSockets → L4; otherwise → L7.

Common: AWS ELB, NGINX, HAProxy. Extreme traffic pushes you into hardware LB territory — rare in interviews, but a clean escape hatch if someone insists the LB itself is the bottleneck.

Queue

Queues buffer bursty traffic and decouple producers from consumers. The producer sends a message and moves on; workers process at their own pace.

Sequence diagram: producer sends message, queue stores it, consumer receives and acknowledges, queue removes message.
Queue buffer — send, store, dispatch, ack, remove.
  • FIFO ordering (most queues); Kafka allows partition-level ordering.
  • Retries + dead-letter queues (DLQ) for poison messages.
  • Partitions scale throughput — pick a partition key that keeps related messages together.
  • Backpressure: a queue that grows forever means you're under-provisioned. Reject or slow producers instead of hoping it drains.

Common: Kafka (streaming + queue), SQS (managed, simple). → Full message queues article

Streams & event sourcing

Streams retain data for a configurable window — consumers can re-read from any point in time. Unlike a one-shot queue, a stream is a durable log.

  • Real-time analytics — engagement events on a social feed.
  • Event sourcing — bank transactions as replayable events; audit and reconstruct state.
  • Pub/sub — one chat message, many room subscribers reading the same stream.
  • Partitioning — scale like DB sharding.
  • Consumer groups — same stream, different processing pipelines.
  • Replication — fault tolerance.
  • Windowing — hourly/daily aggregates for dashboards.

Common: Kafka, Flink, Kinesis.

Distributed lock

Need to hold a resource while one user completes checkout? DB row locks work for a transaction that finishes in milliseconds — not for a 10-minute cart hold sitting open while someone finds their wallet. Use a distributed lock instead (Redis, ZooKeeper).

  • E-commerce — limited-edition sneaker checkout hold.
  • Ride-sharing — lock a driver while the rider confirms the match.
  • Cron jobs — only one server runs the daily aggregation.
  • Auctions — lock an item during final bid processing.
  • Expiry — a TTL auto-releases the lock if the process crashes; without one, a dead process holds the resource forever.
  • Redlock — multi-Redis safe acquisition.
  • Failure mode — deadlocks. Don't acquire locks in inconsistent order across services; always acquire in the same global order or you'll eventually deadlock two requests against each other.

Distributed cache (Redis)

Scale reads and cut latency by keeping hot data in memory. Redis or Memcached clusters sit beside your database, not instead of it.

  • Eviction — LRU, FIFO, LFU when memory fills up.
  • Invalidation — delete the cache entry the moment the underlying row changes.
  • Write-through / write-around / write-back — pick consistency vs. speed deliberately, not by default.
  • Data structures — a sorted set for leaderboards, not just key→string.

Pick: Redis (rich structures) or Memcached (simple strings). Don't cache first and measure never — a cache with no invalidation story just serves stale data confidently. → Caching strategies

CDN

A CDN caches content on edge servers near users. A request routes to the closest point of presence — a hit returns instantly, a miss fetches from origin, caches it, and returns.

  • Static assets — images, video, JS (profile pics, video segments).
  • Semi-dynamic — a blog post updated once daily; cache with a TTL.
  • API responses — high-read, rarely-changing endpoints.
  • TTL + invalidation when origin content changes.

Common: Cloudflare, Akamai, CloudFront. Don't cache anything personalized or write-heavy at the edge — a CDN serving a stale per-user cart page is a bug that files itself.

← Lattice