System-design interview · Core interviews
Design Pastebin
Design immutable text sharing around complete publication, safe rendering and permission checks before introducing independently scaled body storage.
You will learn to
- Trace a complete paste creation and authorized read.
- Explain when object storage helps and how publication remains recoverable.
- Defend private caching, cleanup and transfer limits.
Practice in this chapter
8 interview questions with model answers and follow-ups.
Go to interview practiceUseful foundations: Design a URL shortener · Databases, data models, and ACID transactions · Message queues, event logs, delivery guarantees, and backpressure
Workload and timing examples are interview assumptions.
Dotted concept links open the relevant explanation in a new tab.
01Share text without turning it into executable content
A developer wants to send a diagnostic log to a teammate without copying it into a chat message. They paste the text, receive /p/p7Hk2Lm9, and share the link. Unlike a URL shortener, our service owns the content being returned. It must preserve the saved text, control who may retrieve it and avoid executing anything the author pasted.
Support immutable text, optional expiry, owner deletion, custom aliases and owner listings. Distinguish public, unlisted and private pastes. Public content may be discovered; unlisted content is available to anybody with the address; private content requires an authenticated permission check. An obscure URL alone does not make a paste private.
Assume authenticated creators, a 10 MB maximum and a 10 KB average. Editing, images, collaborative cursors and a public full-text search engine are outside this exercise. A successful creation means the complete intended text is stored, not that an upload merely started. An owner can see a clear failed or processing state when publication cannot finish. Read authorization applies to each new request; bytes a reader already copied cannot be recalled.
Clarify whether a forwarded link should grant access, whether text can change after publication, and whether completion must wait for the entire body. The following requirements choose immutable text with explicit public, unlisted and private access.
02Functional requirements
Agree on these supported actions before selecting components.
Publish immutable text. Authenticated authors create a paste with text, title, visibility, optional custom alias and expiry; publication returns one stable identity.
Retrieve safely. Readers can request a formatted page or raw text. Public and unlisted pastes are accessible under their stated rules; private pastes require a current grant. Pasted markup is displayed as text.
Manage owned pastes. Owners list their pastes, inspect pending/ready/failed status and delete content to prevent new reads.
Recover interrupted creation. A repeated creation key with unchanged content resumes or returns the same paste, rather than publishing another body.
03Non-functional requirements
Use these as illustrative interview assumptions to agree with the interviewer. Numerical targets require measurement; they are not claims about an existing product or a proven implementation. p95 (the 95th percentile) means 95% of measured operations finish within the stated time.
Workload and limits. Use one million creations/day, approximately 116 creates/s and 579 reads/s at peak, a 10 KB average and a hard 10 MB text limit. Ten-year logical content is approximately 36.5 TB before copies.
Read latency. Target regional p95 time to first byte of 200 ms for authorized reads at the planning peak under normal operation. Whole-body transfer time depends on size and client bandwidth; the 10 MB maximum is not promised within 200 ms.
Publication integrity and durability. Success means the complete intended text and its metadata are durable. They must survive an application restart or one storage-node failure within the region; a pending upload is not a published paste.
Privacy and expiry. Every new private read must pass current authorization, including cache hits. Expired or deleted pastes cannot begin a new authorized read; already released bytes cannot be recalled.
Bounded resource use. Enforce byte quotas, upload concurrency and bounded buffering as well as request limits. Slow maximum-size uploads must not exhaust all read capacity.
Retry retention. Keep owner-scoped creation outcomes for at least 24 hours. After that window, clients need explicit status recovery or a new intentional operation rather than an indefinite replay promise.
04Save a log and read it back through one database
The first implementation has an application and a relational database. A creation request contains text, visibility and an owner-scoped request key. Validate the encoding and size, choose a random paste ID, then commit the text, metadata and request result together. After commit, return the paste URL. The database unique constraint prevents two pastes from claiming the same ID or custom alias.
A reader requests p7Hk2Lm9. The app finds its row, checks expiry and deletion, checks the reader's grant if it is private, and sends the stored text. A raw endpoint uses text/plain; a formatted browser page escapes HTML characters before showing them. Pasting <script> must display that text, not run a program in another reader's browser.
The single transaction gives a simple publication rule: either the complete paste exists or none of it is visible. A lost creation response is recovered by looking up the same request key. For modest traffic, storing text in SQL is reasonable. Large retained bodies and slow transfers may eventually make it expensive, but the product name does not decide the database technology.
The baseline publishes text and metadata together; every reader passes access and expiry checks.
Read each connection in order
- syncCreate or retrieve pasteAuthor or reader → Paste application
- syncCommit text / authorized lookupPaste application → Text, metadata and grants
- syncPaste URL or textPaste application → Author or reader
05Separate request rate from retained bytes
Assume one million new pastes per day and five reads per paste. That is about 11.6 creations and 57.9 reads per second on average. A tenfold peak is approximately 116 creations and 579 reads per second. These are not extreme request rates; the storage and large-object cases deserve more attention.
| Estimate | Calculation | Why it matters |
|---|---|---|
| New text | 1M × 10 KB = 10 GB/day | Small records accumulate |
| Ten-year logical content | 10 GB × 365 × 10 = 36.5 TB | Backups and replication include rarely read text |
| Three copies | 36.5 TB × 3 = 109.5 TB | Durability multiplies stored bytes |
| Average outgoing payload | 5M × 10 KB / 86,400 ≈ 0.579 MB/s | Normal egress can remain modest |
| Peak if every upload hits the limit | 116 × 10 MB = 1.16 GB/s | Request limits alone cannot bound byte load |
The final row is a stress case, not the expected average. At five seconds per upload, 116 arrivals/s imply about 580 concurrent uploads in a stable system. Buffering every maximum-size body would consume about 5.8 GB before application overhead. This motivates streaming, bounded concurrency and separate byte quotas. It does not require hundreds of independent services.
06Give clients an identity they can safely retry
Use an idempotency key to identify a creation request.
Creation request
POST /v1/pastes
Idempotency-Key: paste-204
Content-Type: application/json
Example request body
{
"text": "Connection timed out while contacting inventory.",
"title": "Inventory timeout",
"visibility": "private",
"expiresAt": "2030-12-31T23:59:59Z"
}
Store a fingerprint of the validated input so that repeating the key with different text is rejected. The publication outcome determines the response:
| Response | Meaning |
|---|---|
201 with the paste identity |
Publication is complete. |
202 with the same identity and a status URL |
A larger asynchronous upload is explicitly pending. |
| Endpoint | Caller-visible result |
|---|---|
POST /v1/pastes |
Ready paste or explicitly pending upload |
GET /p/p7Hk2Lm9 |
Authorized, safely rendered text |
GET /v1/pastes/p7Hk2Lm9/raw |
Plain-text content |
GET /v1/pastes/p7Hk2Lm9/status |
Owner sees pending, ready or failed |
DELETE /v1/pastes/p7Hk2Lm9 |
Owner prevents new reads; repeated deletion is harmless |
Reject oversized text with 413 and exhausted quotas with 429. Scope owner listing and status reads to authenticated identity. Avoid returning different private error details that reveal whether a guessed paste exists. Specify how long creation-request identities remain recoverable; a documented retry window is more useful than an indefinite promise unsupported by retained records.
Custom aliases are claimed atomically and retained as used identities after deletion. Otherwise an old incident ticket could silently lead to another person's content years later.
07Keep content, metadata and permission roles distinct
The records separate saved content, retry recovery and private access.
| Record | Fields | Purpose |
|---|---|---|
Paste |
ID, owner, title, visibility, creation time, expiry, state; initially also the text | Stores the paste and its publication/access metadata. |
CreateRequest |
ownerId, requestKey, payloadHash, pasteId |
Remembers the result of a creation request. |
Grant |
pasteId, readerId |
Records private access. |
Metadata describes the content; it is not a substitute for storing the content itself.
The common read is an exact paste-ID lookup followed by a permission check. Owner listing needs an index such as (ownerId, createdAt, pasteId). Expiry cleanup needs an index ordered by deadline, so a worker can fetch due batches rather than scan the whole database. Reads still compare the deadline independently: delayed cleanup should waste storage, not extend access.
When body storage grows costly, move text into a private object store and keep its immutable object identity, byte length and checksum in the metadata row. An object store retrieves bytes by key and can scale bulk storage separately from database indexes. This separation introduces an important new question: what should readers see if one store succeeds and the other fails? The answer is a publication state, rather than assuming the two writes are one transaction.
08Publish only after the complete body exists
Publish a body stored outside the database in this order:
- Reserve
p7Hk2Lm9inUPLOADINGstate, with an immutable body name tied to this upload attempt. - Stream the text to object storage using a bounded buffer.
- Verify the stored length and checksum.
- Change the metadata to
READYin a database transaction.
Readers require READY before retrieving the object.
Why this order? If metadata were ready first, a crash before uploading would expose a broken paste. Uploading first can leave an unused object, but that object remains invisible and recoverable. An orphan is storage work to clean up; a ready link pointing to absent bytes is a user-visible correctness failure.
The upload request identity points to the reserved paste. A retry inspects that same attempt and either finishes publication or returns the stored result. It must not silently replace the content under a published cache key. Immutable object names prevent one upload from changing bytes readers already associate with another version.
Cleanup also needs a rule. Before deleting an abandoned attempt's bytes, atomically mark that attempt canceled so it can no longer publish. Publication requires the still-active upload state. The shared state check lets either publication or cancellation win, never both. Detailed lease renewal and multipart recovery are follow-ups; a timer followed by an unguarded object delete is not safe even in the simple design.
A failed publication leaves hidden bytes. A retry must still pass the metadata state check.
Read each connection in order
- syncCreate with request identityAuthor → Paste service
- syncReserve UPLOADING pastePaste service → Metadata
- syncStore and verify complete bodyPaste service → Object storage
- syncCommit READY if upload remains activePaste service → Metadata
- returnPublished paste identityMetadata → Paste service
- returnReady responsePaste service → Author
09Move transfer work out of the metadata bottleneck
A large upload can hold a connection much longer than an indexed metadata read. Give uploads bounded streaming buffers and concurrency limits so slow clients do not consume every reader worker. For larger workloads, separate upload and read capacity. Direct uploads can remove byte transfer from application servers, but the application must still authenticate completion and verify the exact accepted object.
Cache immutable public bodies when repeated reads justify it. Measure distinct hot bytes and byte-hit ratio, not merely the percentage of requests hitting cache. A 10 MB paste can displace many small logs, so impose entry-size or admission limits. Coalesce concurrent misses for the same body and cap object-store requests during cache failure.
Private content may be cached internally, but every delivery still checks current permission. Do not publish a permanent public object URL and expect a private metadata page to protect it. Short-lived signed download links trade reduced authorization traffic for a period during which the link remains usable; negotiate that behavior rather than claiming immediate revocation.
Replicate authoritative metadata and protect object bytes under their own storage policy. Partition metadata only after measured limits justify it. Distributing different paste IDs improves aggregate capacity; one viral paste is primarily a delivery-cache problem.
Meet the one-node-loss target with durable majority commits across three metadata replicas in independent regional failure domains, and object storage whose acknowledged writes survive one storage-node loss. Verify both policies before READY publication; three-copy arithmetic alone is not evidence of either guarantee.
The upload service stores and verifies immutable text before publishing its metadata. A reader service checks visibility and expiry before returning a cached body or loading it from private storage. This diagram keeps delivery behind the service rather than selecting the optional signed-link policy.
Read each connection in order
- syncCreate / upload textAuthor or reader → Upload service
- mediaStore verified bodyUpload service → Private text objects
- syncReserve then publish READYUpload service → Replicated metadata + grants
- syncRetrieve pasteAuthor or reader → Read service
- syncCheck state, expiry and accessRead service → Replicated metadata + grants
- syncAuthorized body lookupRead service → Immutable body cache
- mediaBody on cache missRead service → Private text objects
10Recover publication without exposing partial data
Suppose upload U stores the body, then the application crashes before READY commits. The owner sees no success, and readers still see no published paste. A retry locates U, verifies its stored bytes and asks the database to change the still-active upload to READY. If a cleanup worker already canceled U, the transition fails instead of publishing an object that may be deleted.
If the application crashes after READY commits but before returning, the request result retrieves the same paste. If an object read fails later, return a temporary error; do not report an empty paste as the saved content. A checksum helps identify corruption, while backups and redundant storage provide recovery paths.
Delete metadata before scheduling physical body removal. Store the removal intention in the same transaction as deletion, often as an outbox row: a durable work record that a background worker can retry. Repeated deletion of the exact obsolete object is harmless. Do not delete shared deduplicated bytes merely because one paste no longer uses them; shared storage would require reference accounting.
During a permission-store outage, fail private reads rather than trusting an old grant. Public-content availability can use a separately declared caching policy. These outcomes distinguish unavailable data from missing data and prevent an availability workaround from becoming a privacy leak.
11Watch publication, privacy and byte consumption
Monitor upload-to-ready latency, failed uploads, oldest pending attempts and any READY record whose body cannot be found. Separate metadata latency, time to first byte and whole-transfer duration. A 10 MB response over a 10 Mb/s connection already needs roughly eight seconds before overhead, so one small latency target cannot describe every stage.
Escape rendered text, disable content sniffing for raw delivery and keep object storage private. Rate-limit both requests and bytes. Avoid logging paste contents: diagnostic logs can contain credentials or personal data even when the uploader does not recognize them. Titles, object keys and checksums also need sensible access and retention policies.
Approximate view counts can flow through a bounded asynchronous queue instead of updating the paste row on every read. Measure dropped events and label delayed counts honestly. Cost comes mainly from retained bodies, replicated copies, delivery bytes and object operations. Compression can reduce text storage, but enforce decompressed-size limits.
Test a slow maximum-size uploader, a popular paste after cache loss, a denied private read with a warm cache, and a restore containing both metadata and body objects. Restoring only one side does not restore the service.
12Check the design against the requirements
Use the agreed lists to check the finished design. The tests below still need to establish the targets; a proposed mechanism is not a measured result. FR refers to the numbered functional requirements above; NFR refers to the numbered non-functional requirements.
| Requirement | Design mechanism | Validation and remaining limit |
|---|---|---|
| FR1 + NFR3: complete publication | SQL transaction initially; verified immutable object followed by guarded READY publication after storage separation. | Crash before and after READY. No readable paste may reference incomplete or missing accepted bytes. |
| FR2–3 + NFR4: safe authorized retrieval | Escaped display/plain-text response; current grants, deletion and expiry checks before body delivery. | Read a private paste through a warm cache after access removal; it must be denied. |
| FR4 + NFR6: repeatable creation | Owner/request identity and reserved upload state. | Lose the ready response and retry within 24 hours; return the same paste and immutable body. |
| NFR1–2,5: useful capacity | Separate upload/read capacity, streamed buffers and body caching. | Benchmark p95 first-byte latency with ordinary reads, 10 MB uploads and cache loss; measure full transfer separately. |
| NFR3: one-node loss | Replicated metadata commits and a matching object-storage durability policy. | Fail a node after success and restore metadata plus bodies together. Regional loss requires a separate recovery agreement. |
13Rapid revision
Remember: Store and verify the bytes before READY; hidden unfinished storage is safer than a visible broken paste.
| Decision | Reason | Failure to avoid |
|---|---|---|
| Keep each paste ID’s text unchanged | Shared links keep stable content | Changing text while caches serve old copies |
| SQL baseline | Text and metadata publish in one commit | Introducing two stores without a recovery rule |
| Object storage for large text volumes | Separate large bodies from indexed metadata | Marking READY before the body is complete |
| Reuse the creation request key | Recover a lost creation response | Retrying as an unrelated paste |
| Check expiry and permission on each read | Return unexpired text only to permitted readers | Treating late cleanup or a cache hit as permission |
| Cancel the upload before cleanup | A canceled upload cannot later publish | Deleting a body while its uploader may still publish |
| Count views asynchronously and approximately | Return text without waiting for counting | Claiming exact audit totals from lossy events |
In a spoken summary, begin with saving and retrieving one diagnostic log. Use the estimates to explain why the request rate is manageable while retained bytes may justify object storage. Then show the one crash between byte storage and publication, followed by the private-cache check. That covers the design's central differences from a URL shortener. Editing and strict multi-region revocation add separate requirements rather than following automatically from this architecture.
Practise the interview questions
Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.
What changes compared with a URL shortener?
Reveal a model answer
The service stores and serves the actual text, so completeness, byte transfer, safe rendering and content permissions become central.
Interviewer follow-up
What remains similar?
Reveal the follow-up answer
Stable IDs, uniqueness, request retries, expiry and owner actions still need explicit rules.
What the answer must demonstrate: Names actual content ownership rather than treating the product as another redirect.
Is an unlisted paste private?
Reveal a model answer
No. Anyone with its address can retrieve it. Private content requires an authenticated grant.
Interviewer follow-up
What happens if someone forwards the URL?
Reveal the follow-up answer
Unlisted access follows possession; private access still checks the receiving user.
What the answer must demonstrate: Distinguishes access by URL possession from authenticated access.
Why begin with text in SQL?
Reveal a model answer
At the assumed request rate it provides one simple transaction for text, metadata and retry state.
Interviewer follow-up
What triggers object storage?
Reveal the follow-up answer
Measured retained-byte, backup or transfer pressure, not an arbitrary rule against relational storage.
What the answer must demonstrate: Uses operational pressure to justify losing a one-store transaction.
Why upload the object before marking READY?
Reveal a model answer
A failed upload must not leave a visible paste pointing to missing bytes. Hidden orphan bytes are safer and recoverable.
Interviewer follow-up
What if metadata commit fails?
Reveal the follow-up answer
Retain the pending attempt and verify/retry its publication or cancel it for cleanup.
What the answer must demonstrate: Explains the safe ordering and the orphan-versus-broken-pointer tradeoff.
Why is an old upload not automatically safe to delete?
Reveal a model answer
Its uploader may still be completing. Cleanup must first mark the attempt canceled in the same database state that publication checks, then delete its bytes.
Interviewer follow-up
What does a late uploader do?
Reveal the follow-up answer
Its READY transition fails once the attempt is canceled; it cannot bypass that guard.
What the answer must demonstrate: Identifies a state guard shared by publication and deletion.
Can we cache private paste bodies?
Reveal a model answer
Internally, yes, provided every new delivery passes the required current permission check.
Interviewer follow-up
What about a permanent public object URL?
Reveal the follow-up answer
That bypasses the permission service and violates private access.
What the answer must demonstrate: Keeps permission enforcement in front of every byte-delivery path.
Why limit bytes as well as requests?
Reveal a model answer
A maximum-size paste consumes far more bandwidth and buffering than an average one. Request counts alone hide that imbalance.
Interviewer follow-up
Does streaming solve unlimited concurrency?
Reveal the follow-up answer
No. Bounded buffers still require connection, byte-rate and active-upload limits.
What the answer must demonstrate: Connects object size, transfer time and bounded resources.
How would editing change the design?
Reveal a model answer
Store immutable body versions and atomically change the selected version using an expected-version check.
Interviewer follow-up
Why not overwrite one cached object?
Reveal the follow-up answer
Different caches may serve different content under the same identity, defeating stable reads.
What the answer must demonstrate: Separates immutable content versions from mutable selection metadata.
Blank-page exercise · 45 minutes
Build the answer yourself
Design an immutable paste service with public, unlisted and private text, 1M creations/day and a 10 MB maximum. Explain a working baseline and its transition to object storage.
- Clarify and number functional and non-functional requirements in 5 minutes: visibility, immutable publication, first-byte latency, byte limits and durability.
- Trace create/read through one database in 8 minutes.
- Estimate normal and maximum-object load in 7 minutes.
- Define API, metadata and publication state in 10 minutes.
- Explain a crashed upload, cleanup race and private cache hit in 10 minutes.
- Use 5 minutes to review the final design against the numbered FR/NFR lists, test publication and private reads, and state transfer-time and recovery limits.
Check that each component and design decision follows from your requirements and workload.
Recall the key ideas
Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.
Design PastebinThe body upload succeeds, but the application crashes before READY. What can readers see, and how does recovery proceed?Recall first, then reveal
Readers see no published paste. A retry verifies the stored body and publishes only if the upload is still active; a canceled attempt stays unavailable.
Bytes first, READY second.
Return to lessonDesign PastebinA cache contains a private paste. Is that enough to return it?Recall first, then reveal
No. The service must still check whether this reader may access the paste.
Stored is not authorized.
Return to lessonDesign PastebinWhen may cleanup delete the body of an abandoned upload?Recall first, then reveal
After saving a cancellation that prevents the uploader from publishing it later.
Cancel publication, then reclaim.
Return to lessonFinal revision
Summary and interview notes
A paste combines text, metadata and access rules. When text moves to object storage, verify its upload before publication and cancel abandoned uploads before deleting their bytes.
Remember these points
- Unlisted and private mean different access contracts.
- Read-time checks enforce expiry independently of cleanup.
- Hidden orphan bytes are preferable to a broken visible paste.
- Large transfers need byte and concurrency limits.
Interview tips
- Start with one saved log and one reader.
- Use a crash between object write and READY to test the design.
Important qualifications
- Exact public revocation deadlines and renewable upload leases require additional protocol detail.
Continue after the core interview
Explore the advanced version
The advanced lesson keeps the full detailed design. Use these sections when you want to examine the stronger requirements and failure cases.
- Publication versus garbage collection proof
Useful when uploads have renewable leases and collectors run concurrently.
- Exact public visibility deadlines
Needed when public edge caches must satisfy a provable revocation limit.
- Regional restoration of aliases and grants
Needed when backup recovery may omit recent claims or revocations.
- Private streaming integrity and capabilities
Useful when direct delivery replaces application-mediated reads.
Technical references
- Amazon S3 data consistency modelConfirms object read-after-write behavior; it does not provide a transaction with a separate metadata database.
- Transactional outbox patternSupports the reliable handoff from a committed deletion to asynchronous cleanup.
- Amazon S3: Conditional WritesVerified conditional creation prevents overwriting an existing generation; metadata publication remains a separate transaction.
- Amazon S3: Checking Object IntegrityVerified explicit checksums rather than assuming every ETag is a whole-object hash.
Practice marks stay in this browser.