Guide

Once requirements and numbers are set, define the interface and the data. Together these take about ten minutes. A good API and data model make the high-level design almost obvious. A weak one leaves you guessing for the rest of the interview.

The API

Define one endpoint or message per functional requirement. Use REST unless there is a reason not to, such as streaming or two-way messages, and say why if you choose something else. For the deeper rules, see API design.

HTTP
POST /v1/posts                     { "text": "...", "mediaIds": ["m_123"] } → 201 { "postId": "p_987" }
GET  /v1/feed?cursor=abc&limit=20  → 200 { "items": [...], "nextCursor": "def" }
POST /v1/users/{id}/follow         → 204

Small details show seniority:

  • The user ID comes from the auth token, not the request body.
  • Lists are paginated with cursors, not offsets. New posts shift offsets, so pages skip or repeat items. A cursor points at a position, so it stays stable.
  • Mutating endpoints accept an idempotency key. See idempotency.
  • Real-time features use a WebSocket or server-sent events channel, and you name the message types.

The data model

List the core entities, their key fields and their main access patterns. Then pick a store for each one. The access pattern decides the store, not the other way round. See databases.

User      (user_id PK, name, created_at)                  → Postgres
Post      (post_id PK, author_id, text, media_keys, ts)   → sharded KV or wide-column, by post_id
Follow    (follower_id, followee_id, ts), PK on both       → indexed both ways
Timeline  (user_id → list of post_ids)                    → Redis, derived and rebuildable
Media     (blob)                                          → S3 and a CDN

Say which data is the source of truth and which is derived. Caches, timelines and search indexes are derived. Derived data can be rebuilt, so it can live in a faster store that is less durable.

Common mistakes

  • Taking the user ID from the request body. Anyone can change it. Take it from the token.
  • Offset pagination over changing data. Pages skip or repeat items as rows arrive.
  • Choosing a store before the access pattern. Name the reads and writes first.
  • No source-of-truth line. Without it, nobody knows which copy to rebuild from.

Check yourself

1. Why paginate a feed with cursors instead of offsets? New posts shift offsets, so pages skip or repeat items. A cursor points at a position in the data, so it stays stable as new items arrive.

2. Why is the timeline store allowed to be less durable than the post store? The timeline is derived. It can be rebuilt from the posts table, so losing it costs time, not data.

Key takeaways

  • One endpoint per functional requirement, with the user identity from the auth token.
  • Cursors for lists, idempotency keys for mutations, and named message types for real-time channels.
  • Pick each entity's store from its access pattern.
  • Mark each piece of data as source of truth or derived.

Further learning

The API design page covers versioning, error shapes and pagination in more depth.

Next, use the design to work through hard problems in high-level design, deep dives and trade-offs.