DEV Community

Cover image for Design Pastebin: the beginner-friendly system design interview walkthrough
Gowtham Potureddi
Gowtham Potureddi

Posted on

Design Pastebin: the beginner-friendly system design interview walkthrough

Design Pastebin: the beginner-friendly system design interview walkthrough

The request to design Pastebin sounds like one line — paste some text, get a short link, share it — and that one line is exactly why it is the best first system design interview you can practise. It looks almost identical to a URL shortener, so the moves are foundational, yet it hides one real twist that teaches the core of storage design: a shortener remembers a tiny web address, but Pastebin stores and serves arbitrary-size content that has to expire. That single difference is what turns a toy into a proper HLD, and learning to spot it is the whole lesson.

The round turns on one structural insight. "Paste text, get a link" looks like a shortener until you ask where a megabyte of pasted logs actually goes — and the answer is not in the little database that maps your link to it. The body of a paste belongs in blob (object) storage, kept apart from the small, queryable metadata that records the key, where the body lives, and when it expires. From there everything follows: the system is overwhelmingly read-heavy (a paste is written once and read many times), so it is cache-first behind a CDN; and because every paste carries a TTL, old content is swept away and the storage footprint stays small. Get that reframe — a URL shortener plus arbitrary-size content plus expiry — and the rest of the Pastebin system design is three clean decisions: how to mint a short unique key, where the body lives and how reads scale, and how pastes expire. This walkthrough follows the path a strong candidate draws on the whiteboard — requirements, estimate, API and data model, high-level design, then the deep dives — naming the follow-up the interviewer uses at each step to tell a memorised answer from real understanding.

Title card for a beginner-friendly system design interview walkthrough on designing Pastebin, showing text being pasted and turned into a short link, the large body stored in a blob store separate from a small metadata database, served read-heavy through a cache, with a TTL clock marking expiry, on a dark citrus-and-lavender background.

How the Pastebin round is actually run

A Pastebin round runs about 45 minutes on a shared canvas — you draw the boxes and arrows while you talk, and the interviewer interrupts. It is a favourite first system because the requirements are small enough to hold in your head, so the round is really a test of judgement: can you keep a simple product simple while still making the right calls on storage, read scaling and cleanup, instead of either under-thinking it ("just a database") or over-building it with machinery it does not need. The clock is a touch tighter than the hour-long rounds, which suits a focused problem — spend your minutes on the key, the storage split, and expiry.

The interviewer rarely lets "it's basically a URL shortener" stand. "Fine — so what's actually different from a shortener, and when someone pastes a megabyte of logs, where does that text go and why not just put it in the database?" That question — content storage, not link mapping — is the one a copied answer can never rehearse, and the one this round is really testing.

The rounds here are modelled on how the loop runs, not scraped from any candidate's recall. What matters for prep is the shape: a blank canvas, a tighter clock, and a follow-up after every decision you make.

The five-step framework for any HLD round

Every high-level design answer fits the same spine. Say it out loud at the start so the interviewer knows you have a plan, then walk it:

  1. Clarify requirements — functional and non-functional, and what you are explicitly not building.
  2. Estimate — reads versus writes and the size of a paste, to justify every later choice.
  3. High-level design — the boxes and arrows: the write path that mints a key and stores the body, and the read-heavy path that serves it.
  4. Deep dive — the two or three decisions that actually decide this system.
  5. Follow-ups — bottlenecks, failure modes, and what you would change at ten times the scale.

What the debrief measures

The score is not "right or wrong design." A good HLD debrief reads on four dimensions, and every move below maps to one: problem solving (did you see past "URL shortener" to arbitrary-size, read-heavy, expiring content), communication (did you say why the body goes to blob storage and not the metadata DB, in a single sentence), technical execution (a collision-free key, metadata separate from the blob, cache-first reads behind a CDN, and a TTL with lazy delete plus cleanup), and time management (did you keep a simple product simple and spend your 45 minutes on storage and expiry, not on re-deriving base62). Reading a walkthrough teaches the design; it does not teach you to deliver it on the clock while someone pushes back.

Step 1 — Requirements: what Pastebin must do

Spend the first few minutes here. Jumping to boxes before you have scoped the problem is the fastest way to design the wrong system.

Type Requirement
Functional A user pastes text and gets back a short, unique link; anyone opening that link reads the content; the user can set an expiry; pastes can be public, unlisted, or private.
Functional (optional) Syntax highlighting, custom aliases, edit-after-create, view analytics — call these out, then scope most of them for later.
Non-functional Read-heavy (far more reads than writes); highly available; content durable until it expires; low-latency reads; cheap storage that does not grow without bound.

The sentence that earns points: "It's a URL shortener plus two things — the body is arbitrary-size content, so it lives in blob storage separate from the metadata, and every paste expires, so the footprint stays small; and it's read-heavy, so it's cache-first." Say that and you have framed the entire design before drawing a box.

Step 2 — Capacity estimation (back of the envelope)

Estimation here is about proving three things: reads dominate writes, a paste can be large, and expiry keeps storage bounded.

Quantity Assumption Result
Writes modest — some pastes per second at peak ordinary write volume; the write path is not the scaling problem
Reads each paste read many times (shared links) reads dominate by orders of magnitude — the design must be cache-first
Paste size a few lines up to several megabytes too big to sit inline in the metadata DB — the body belongs in blob / object storage
Active footprint daily writes × an expiry window of days bounded — expiry caps total storage at roughly a few days of pastes, not forever

Two conclusions fall out, and you should say both out loud. First, reads are the axis that matters — writes are cheap and occasional, but the same link can be opened thousands of times, so the design leans on a cache and a CDN and treats storage as read-mostly. Second, expiry is what keeps it cheap — because every paste has a TTL, you are never storing the whole history of the internet, just a rolling window, which also shapes how you clean up. You have now pointed the interview at the real deep dives — the key, the storage split, and expiry — before anyone asked.

Step 3 — API and data model

The API is deliberately small: create a paste, read it, maybe delete it.

Operation Shape
create_paste(content, expiry, visibility) stores the body, writes metadata, and returns the short key / URL.
get_paste(key) returns the paste content (or a 404 if missing or expired).
delete_paste(key) removes a paste before its expiry (owner action).

The data model is thin, and the whole trick is in the split: small metadata in a datastore, the large body in a blob store.

Entity Notes
paste_metadata key, blob_location, created_at, expires_at, size, visibility — small, queryable, keyed by the short key; the index into everything.
paste_body the raw pasted text, stored in blob / object storage at blob_location — large and opaque, never inline in the metadata DB.

Step 4 — High-level design: the write path and the read path

Now the boxes. Clients hit stateless app servers behind a load balancer, and the system splits cleanly into a modest write path and a read-heavy read path:

  • Write path: an app server asks a key-generation service for a short unique key, stores the body in the blob / object store, writes the metadata (key → blob location, created, expires_at, size, visibility) to the datastore, and returns the key as a URL.
  • Read path: GET /{key} looks up the metadata, then fetches the body cache-first — from an in-memory cache or CDN on a hit, falling through to the blob store only on a miss — and serves it.
  • Cache + CDN: because a paste never changes after creation, it caches beautifully; hot pastes live in cache and at CDN edges, so the blob store sees only misses.
  • Stateless servers: the app tier holds no session state, so it scales horizontally behind the load balancer.
  • Expiry sweeper: a background job (or native store TTL) removes pastes whose expires_at has passed, keeping storage bounded.

Say explicitly that the small metadata and the large blob are stored separately, and that reads are cache-first because a paste is immutable. Naming that split — key-gen plus metadata plus blob, with a cache in front — is a signal the interviewer is listening for.

A Pastebin architecture diagram showing a write path where a client request hits stateless app servers behind a load balancer, which generate a short key via a key-generation service, store the paste body in a blob object store and the metadata in a datastore, then return the key; and a read path where a request looks up metadata by key and fetches the body cache-first from an in-memory cache or CDN, falling through to the blob store on a miss, with a background expiry sweeper removing expired pastes.

Deep dive: generating the short, unique key

This is the first decision, and it is the half Pastebin shares with a URL shortener — so name that kinship, get it right, and keep it tight rather than re-deriving it for ten minutes. The follow-up is about collisions: how do two app servers both hand out keys without ever clashing?

You need a key that is short, URL-safe, and collision-free. The common approaches, as tradeoffs:

Approach What it optimises / costs
Counter + base62 a key-generation service (or a distributed counter) hands each app server a range of numbers; encode each in base62 (A–Z a–z 0–9). Guaranteed unique with no collision check, and ~7 chars covers a huge keyspace — the clean default.
Random + collision check generate N random URL-safe characters and check the datastore for a clash, retrying on the rare hit. Simple and unguessable, but needs a read before every write.
Hash + truncate hash the content (plus a salt/time) and take a prefix. No coordination, but collisions must still be handled and identical content can map to the same hash.

Reach for counter + base62: pre-allocating ranges to each writer means two servers never pick the same key and neither needs to check for collisions, which keeps the write path fast. Base62 keeps the key short and safe to drop straight into a URL. If the requirement is that unlisted pastes be unguessable, lean toward a random key (or add random bits) so the next key can't be inferred from the last. Saying out loud that this is the same core problem as a URL shortener — and that the interesting part of Pastebin is the storage, not the key — shows you know where to spend your minutes.

"How do two app servers both hand out keys without ever colliding?" I don't let them pick freely. A key-generation service hands each server a pre-allocated range of numbers, and each is encoded in base62, so two servers draw from disjoint ranges and can never produce the same key — no collision check needed on the write path. If I also need unlisted pastes to be unguessable, I add random bits so the next key can't be inferred from the last.

System Design
HLD · Storage & files · 45 min
Design Pastebin out loud, with follow-ups

Practise on Zynter →

Deep dive: storing the paste — metadata vs blob, and read-heavy serving

This is the decision that makes Pastebin more than a shortener, and the one the round is really about. The follow-up is blunt: someone pastes a megabyte of logs — where does that go, and why not in the database?

The answer is that the big body does not belong in your metadata database. Row stores are built for small, structured, queryable records — not for multi-megabyte opaque blobs, which bloat the rows, slow every query, and waste the database's expensive strengths on bytes it never needs to index. So you split storage by shape:

  • Metadata in a datastore: key → blob_location, created_at, expires_at, size, visibility — small, indexed by the short key, cheap to query. This is what the read path hits first.
  • Body in blob / object storage: the raw text sits in an object store (S3-style) at blob_location, which is built for large, cheap, durable, write-once objects. The metadata points to it.
  • Read is metadata-then-blob, cache-first: GET /{key} looks up the metadata, then fetches the body — served from an in-memory cache or a CDN on a hit, and from the blob store only on a miss.
  • Immutable means cacheable: a paste never changes after it is written, so it can be cached aggressively and sit at CDN edges indefinitely (until it expires) — exactly what makes a read-heavy system cheap.

The point to state plainly: separating the small, queryable metadata from the large, opaque blob is the Pastebin-specific move, and it is what lets reads scale through a cache and CDN while the database stays lean. A URL shortener never needs this because its "body" is a single short string; Pastebin does, because its body is content.

"Someone pastes a megabyte of logs — where does that go, and why not in the database?" Not in the metadata database — a row store is for small, queryable records, and a multi-megabyte blob would bloat the rows and slow every query. The body goes to blob / object storage, which is built for large, cheap, durable objects, and the metadata just holds a pointer to it. The read path looks up metadata by key, then serves the body cache-first from a CDN — and because a paste never changes, it caches beautifully.

A storage diagram contrasting a small metadata datastore keyed by paste id that holds the key, blob location, timestamps, size and visibility, against a blob object store that holds the large paste body, with a read path that looks up metadata by key then fetches the body cache-first from an in-memory cache and CDN, falling through to the blob store only on a miss.

System Design
HLD · Storage & files · 45 min
Defend the metadata-vs-blob storage split out loud

Practise on Zynter →

Deep dive: expiration, TTL and keeping it clean

Storage decides where a paste lives; this decides when it leaves — and it is the piece that keeps the whole system cheap. The follow-up is about the mechanics: a paste is set to expire in an hour — what actually deletes it, and what does a reader see after?

Every paste carries an expires_at, set by the user or a default. You enforce it with two mechanisms working together, because either alone has a gap:

  • Lazy deletion on read: when a get_paste arrives, check expires_at; if it has passed, treat the paste as gone — return a 404 and don't serve stale content. This guarantees correctness instantly, even before anything is physically removed.
  • Background cleanup (or native TTL): a sweeper job periodically deletes expired pastes from the blob store and metadata datastore — or you set a native TTL on the records so the store evicts them for you. This reclaims space so storage stays bounded, which lazy deletion alone would not do (an un-read expired paste would linger forever).
  • Why both: lazy deletion keeps reads correct the instant a paste expires; the cleanup job keeps storage bounded over time. Together they mean a reader never sees expired content and you never pay to store it.

While you are here, name the cheap, mature guards the interviewer wants to hear: pastes can be public, unlisted, or private, and a hard-to-guess key makes an unlisted paste effectively unreachable without the link; and the write path is rate-limited so the service can't be flooded with spam pastes. These are the "sound choices" that show judgement without over-building.

"A paste is set to expire in an hour — what actually deletes it, and what does a reader see after?" Two things working together. On read, I check expires_at and return a 404 the moment it has passed, so no one ever sees expired content — that's lazy deletion. Separately, a background cleanup job (or a native TTL on the store) physically removes expired pastes from the blob and metadata stores so the footprint stays bounded. Lazy deletion keeps reads correct instantly; the sweeper keeps storage cheap over time.

An expiration diagram showing each paste carrying an expires_at timestamp, enforced two ways together: lazy deletion where a read after expiry returns a 404 and marks the paste gone, and a background cleanup job or native store TTL that physically removes expired pastes so storage stays bounded, with a note that a hard-to-guess key keeps unlisted pastes private and rate limiting guards the write path against abuse.

The follow-ups that decide the Pastebin round

Scan the probes from each deep dive and they rhyme. Master these five and you are ready for a version of the question that is not drawn exactly like this one.

  • "How is this different from a URL shortener?" → Same key-generation half, but Pastebin stores and serves arbitrary-size content that expires: the body goes to blob storage separate from the metadata, reads are cache-first, and everything has a TTL. (problem solving)
  • "How do you generate a unique key without collisions?" → A key-generation service hands each writer a pre-allocated range encoded in base62, so two servers never collide and no collision check is needed; add random bits if unlisted pastes must be unguessable. (technical execution)
  • "Where does the paste body live, and why not the database?" → In blob / object storage, which is built for large, cheap, durable objects; the metadata database only holds a small pointer plus timestamps, so queries stay fast and the big content caches well. (communication)
  • "It's read-heavy — how do you scale reads?" → Cache-first: an in-memory cache and a CDN serve hot pastes, and since a paste is immutable it caches aggressively; the blob store only sees misses, and app servers are stateless behind a load balancer. (technical execution)
  • "How do pastes expire without storage growing forever?" → Lazy deletion returns a 404 on read the instant expires_at passes, and a background cleanup job or native store TTL physically removes expired pastes, so reads stay correct and the footprint stays bounded. (problem solving)

Each maps to a debrief dimension. Reading this list teaches you the answers; it does not teach you to deliver them while someone interrupts — that only comes from saying them out loud.

How to prepare: a one-week plan

You do not need fifty systems. You need this one cold and the framework automatic, so the next "design X" is just new nouns in the same five steps.

  • Days 1–2: Learn the five-step framework until it is reflex. Do Pastebin end to end on paper — requirements, estimate, API, data model, and the write-path/read-path boxes.
  • Days 3–4: Drill the key and the storage split: counter + base62 keys, and why the body goes to blob storage while metadata stays in the datastore, served cache-first. Say each tradeoff in one sentence.
  • Days 5–6: Own expiry and read scaling — lazy deletion plus a cleanup job, the cache and CDN, and the public/unlisted/private + rate-limiting guards. Answer each of the five follow-ups out loud.
  • Day 7: A full timed 45-minute round, narrating the whole way, with someone (or something) interrupting. This is the rep that counts.

This post is the deep walkthrough behind one row of the broader Top 25 system design interview questions — once Pastebin is automatic, the same spine carries the rest of the list.

Frequently asked questions

How do I design Pastebin step by step?

Follow the five-step HLD framework. Clarify requirements (paste text and get a short unique link; open the link to read the content; set an expiry; public / unlisted / private); estimate to show it is read-heavy, that a paste can be large, and that expiry keeps storage bounded; define the small API (create_paste, get_paste, delete_paste) with the key split — small metadata in a datastore, the large body in blob storage; draw the design (stateless app servers behind a load balancer; a write path that mints a key, stores the body in the blob store and the metadata in the datastore; a read-heavy path that looks up metadata and serves the body cache-first from a cache or CDN; an expiry sweeper); then deep-dive the key generation, the metadata-vs-blob storage, and expiration. Finish on the follow-ups about collisions and where the body lives.

How does Pastebin generate a unique key for each paste?

With a short, URL-safe, collision-free key — most cleanly a counter plus base62. A key-generation service (or distributed counter) hands each app server a pre-allocated range of numbers, and each number is encoded in base62 (A–Z, a–z, 0–9), so two servers draw from disjoint ranges and can never produce the same key, with no collision check needed on the write path; roughly seven base62 characters already cover a huge keyspace. Alternatives are generating a random URL-safe string and checking the datastore for a clash, or hashing the content and truncating. If unlisted pastes must be unguessable, use random keys (or add random bits) so the next key can't be inferred from the last. It is the same key problem as a URL shortener.

Where is the paste content stored — the database or object storage?

The large paste body goes in blob / object storage, not the metadata database. A relational or row store is built for small, structured, queryable records, and a multi-megabyte blob would bloat the rows and slow every query. So the body lives in an object store (S3-style) that is built for large, cheap, durable, write-once objects, and the metadata database holds only a small record — the key, the blob's location, timestamps, size and visibility — keyed by the short key. The read path looks up the metadata, then fetches the body cache-first. Separating the small, queryable metadata from the large, opaque blob is the move that distinguishes Pastebin from a URL shortener.

How do you scale Pastebin for read-heavy traffic?

By making reads cache-first, which works because a paste is immutable once written. Hot pastes are served from an in-memory cache and from a CDN at the edge, so the same shared link can be opened thousands of times without touching the blob store, which only sees cache misses. App servers are stateless behind a load balancer so they scale horizontally, and the metadata datastore and blob store are read-replicated. Writes are modest and do not need the same machinery. Because content never changes after creation, aggressive caching is safe and cheap — exactly what a read-heavy, write-once workload wants.

How does paste expiration and TTL cleanup work?

Each paste stores an expires_at timestamp, and you enforce it two ways at once. Lazy deletion handles correctness: when a read arrives, you check expires_at and return a 404 the moment it has passed, so a reader never sees expired content even before anything is physically removed. A background cleanup job — or a native TTL on the blob store and datastore — handles space: it periodically deletes expired pastes so storage stays bounded, which lazy deletion alone would not do because an un-read expired paste would linger forever. Together they keep reads correct instantly and storage cheap over time, so the active footprint is only a rolling window of pastes rather than the whole history.

How do I practise a system design interview out loud?

Reading a walkthrough is not the same as defending a design while someone interrupts. On Zynter, the HLD track runs live voice rounds modelled on how real system design loops run — you talk through a shared design on the canvas, and a voice interviewer pushes with the follow-ups above one at a time, then gives you a debrief on problem solving, communication, technical execution, and time management. The score is a practice signal, not a hiring decision.

Practise it on Zynter

You can read why the body goes to blob storage. The round is won on saying it under follow-ups.

Pick the Pastebin round, draw the write-path and read-path design on the canvas, and defend it out loud to a voice interviewer that keeps asking "how is this different from a URL shortener?" and "where does a megabyte of pasted text go?" — then read the debrief. Zynter.ai is on-demand mock interviews modelled on real company loops, with 150+ rounds across 20 companies including the HLD system design track (Sep 2026).

Practise the Pastebin round →
Browse all interview tracks

Top comments (0)