Pastebin
Design a Pastebin-style service for storing and sharing text snippets with expiry and access control.
Problem Statement
Design a Pastebin-style service for sharing text snippets. A user creates a paste containing plain text or code and receives a compact, unique key that can be shared as a short URL. Readers open the key to view the content with low latency, optional syntax highlighting, and policy controls such as expiration, one-time access, visibility, and password protection.
At interview scale, the system is read-heavy but has a modest write rate. The important distinction from a URL shortener is that the service stores and serves the content itself rather than just returning a redirect. Small pastes can live inline with metadata for a single lookup, while large pastes should move to object storage with the metadata database holding a pointer.
The default design should optimize for durable paste creation, fast public reads through cache and CDN, safe handling of private or burn-after-read content, and abuse controls that prevent the platform from becoming a spam, malware, or data-exfiltration hub.
Business use case
Paste services are useful for developers sharing logs, stack traces, code snippets, configuration examples, incident notes, and temporary text with teammates or support staff. They reduce friction when the content is too large for chat but too lightweight for a document system.
Businesses use this pattern inside support tooling, developer portals, incident response, interview platforms, and collaboration products. Public or unlisted pastes prioritize simple sharing, while enterprise variants need private access, audit trails, retention controls, and abuse operations.
Functional Requirements
Create a paste from text content and return a unique, compact paste key and URL.
Retrieve and render a paste by key, including raw text and syntax-highlighted views.
Store small pastes inline in the metadata database and large pastes in object storage with a pointer.
Support expiration or TTL so pastes stop serving after a configured deadline.
Support one-time burn-after-read pastes that become unavailable after the first successful read.
Support visibility modes: public, unlisted, private, plus optional password protection.
Scan content for abuse, spam, malware indicators, secrets, or policy violations.
Collect view analytics such as total views, referrer, coarse geography, and device class.
Non-Functional Requirements
Latency
Public paste reads should complete under 100ms p99 inside a region for cached small pastes and under 250ms p99 for large pastes that require object storage access. Create requests can be slower because they validate size, persist content, and enqueue scanning, but should usually finish under 300ms p99.
Availability
Reading active public pastes is the critical path and should target 99.99 percent availability. Management APIs, analytics dashboards, and asynchronous scanning can degrade without taking down safe paste reads.
Read-heavy scalability
Assume roughly 50 reads per paste creation. CDN caching, Redis or Memcached, and object-storage edge caching should absorb hot public reads, while private, password-protected, or one-time pastes bypass shared caches.
Durability
A successfully created paste should not disappear before its retention deadline. Persist metadata and inline content in a replicated database, write large bodies durably to object storage, and only acknowledge creation after both metadata and required content are committed.
Consistency
Creation needs read-after-write behavior for the author. Expiration, deletion, abuse takedowns, and burn-after-read state need strong enough consistency to prevent stale content from being served after it should be unavailable.
Privacy and access control
Private and password-protected pastes must not leak through public caches, search indexing, analytics, referrer headers, or predictable keys. One-time pastes require atomic read consumption.
Cost efficiency
Text bodies can dominate storage and bandwidth. Inline only small content, compress large objects, apply retention policies, cache hot reads, and avoid storing full view events in the serving database.
Capacity Estimation
Assumptions
Assume 30M new pastes per month, a 50:1 read to write ratio, 30 days per month, a 10x peak multiplier, and a default retention window of 12 months after TTL cleanup. Average metadata is 1 KB per paste.
Assume 85 percent of pastes are small enough to store inline with an average body size of 8 KB. The remaining 15 percent are large pastes with an average compressed object size of 512 KB. Enforce a maximum paste size such as 10 MB for anonymous users and higher limits for trusted accounts.
New pastes
30M per month
About 1M per day
Average write QPS
12 writes per second
30M divided by 30 days divided by 86,400 seconds
Peak write QPS
120 writes per second
10x average peak
Average read QPS
580 reads per second
50 reads per write
Peak read QPS
5,800 reads per second
10x average peak
Monthly inline content
204 GB raw
25.5M small pastes times 8 KB
Monthly object content
2.3 TB raw
4.5M large pastes times 512 KB
Twelve-month raw content
About 30 TB
Inline plus object content before replication, compression variance, and lifecycle cleanup
Metadata storage
360 GB raw per year
360M paste records times 1 KB
Hot cache memory
30 to 50 GB
A few million hot small paste records plus Redis overhead and replication
Keyspace
8-character base62 gives about 218T keys
Enough headroom for random, non-enumerable keys over many years
Calculations
- Writes: 30M creates per month divided by 30 days is 1M creates per day. 1M divided by 86,400 seconds is about 11.6 writes per second, rounded to 12.
- Reads: with a 50:1 read to write ratio, average read traffic is about 580 reads per second.
- Peak: using a 10x multiplier gives about 120 write QPS and 5,800 read QPS.
- Inline content: 85 percent of 30M is 25.5M small pastes. 25.5M times 8 KB is about 204 GB per month.
- Object content: 15 percent of 30M is 4.5M large pastes. 4.5M times 512 KB is about 2.3 TB per month.
- Retention: monthly content of about 2.5 TB for 12 months gives about 30 TB raw before database replication, object-storage durability overhead, compression differences, and lifecycle cleanup.
- Metadata: 30M records per month times 12 months is 360M records. At 1 KB each, metadata is about 360 GB raw.
- Cache: if a few million popular small pastes drive most public reads, caching them at roughly 8 to 10 KB each plus memory overhead requires tens of GB, so plan 30 to 50 GB across the replicated hot cache tier.
- Keyspace: 62 to the power of 8 is about 218 trillion combinations. That provides large safety margin and makes random guessing harder than short sequential keys.
API Design
/api/v1/pastesCreates a paste. The caller may be anonymous or authenticated. The service validates size, visibility, TTL, password policy, and language hint, then stores content inline or in object storage based on size.
Request
{
"content": "public class Example { }",
"language": "java",
"visibility": "unlisted",
"expiresAt": "2026-08-02T12:29:19Z",
"burnAfterRead": false,
"password": "optional-client-supplied-password"
}
Response
{
"pasteKey": "aB7kP9xQ",
"pasteUrl": "https://paste.example.com/aB7kP9xQ",
"visibility": "unlisted",
"contentLocation": "inline",
"createdAt": "2026-07-26T12:29:19Z",
"expiresAt": "2026-08-02T12:29:19Z",
"scanStatus": "pending"
}
201— Created400— Invalid content, size, TTL, language, or visibility401— Authentication required for private or account-only features413— Paste exceeds size limit429— Rate limit exceeded
/{pasteKey}Returns the rendered paste page. Public and unlisted pastes can be served through CDN when policy allows. Private, password-protected, expired, blocked, or one-time pastes require service-side checks.
Response
HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Cache-Control: public, max-age=300 Rendered paste page with escaped content and syntax highlighting.
200— Paste rendered401— Authentication or password required403— Caller is not allowed to view this paste404— Unknown paste key410— Expired, deleted, blocked, or already burned
/api/v1/pastes/{pasteKey}/rawReturns the raw text body for clients, command-line tools, or copy workflows. The endpoint applies the same access, expiration, password, and burn-after-read checks as the rendered view.
Response
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Cache-Control: private, no-store
public class Example { }
200— Raw paste returned401— Authentication or password required404— Unknown paste key410— Expired, deleted, blocked, or already burned
/api/v1/pastes/{pasteKey}Soft-deletes a paste owned by the authenticated user or disabled by an abuse operator. The metadata remains for audit and analytics retention, but reads return 410 Gone.
Response
{
"pasteKey": "aB7kP9xQ",
"status": "deleted"
}
200— Deleted or disabled401— Authentication required403— Caller does not own the paste404— Paste not found
/api/v1/pastes/{pasteKey}/analyticsReturns aggregate view analytics for an owned paste. The endpoint reads from the analytics store and should not query raw event streams on demand.
Response
{
"pasteKey": "aB7kP9xQ",
"totalViews": 18420,
"uniqueVisitorsEstimate": 9720,
"topReferrers": ["direct", "docs", "chat"],
"dailyViews": [
{ "date": "2026-07-26", "views": 620 }
]
}
200— Analytics returned401— Authentication required403— Caller cannot view analytics for this paste404— Paste not found
Keep the anonymous read endpoint simple, but do not treat every paste as cacheable. CDN caching is safe for public, non-password, non-burn, non-private pastes with a future TTL and clean scan status. Private and one-time reads must be served by the application so authorization and atomic state changes happen before content is returned.
Database Design
The serving record is keyed by paste_key because every read starts with that key. The metadata row should be enough to decide visibility, expiration, status, content location, cacheability, and whether additional checks are required.
Small text is stored inline to make common reads a single database or cache lookup. Large text is stored in object storage, and the metadata row stores the object URI, content hash, size, and scan state. This split avoids bloating database pages and keeps large byte serving cost-efficient.
| paste_key | varchar(16) | Primary key; generated base62 key or validated custom key |
| owner_user_id | uuid nullable | Owner for private pastes, deletion, and analytics |
| visibility | varchar(20) | Public, unlisted, or private |
| content_location | varchar(16) | Inline or object |
| inline_content | text nullable | Small paste body stored directly in the row |
| object_uri | text nullable | Pointer to compressed large content in object storage |
| content_size_bytes | integer | Original text size before storage overhead |
| content_hash | char(64) | Digest used for deduplication, integrity checks, and abuse signals |
| language | varchar(64) | User-selected or detected language for syntax highlighting |
| password_hash | varbinary nullable | Strong salted password hash; never store the clear password |
| expires_at | timestamp nullable | Null only when product policy allows no explicit expiration |
| burn_after_read | boolean | If true, the first successful read consumes the paste |
| remaining_reads | integer nullable | Usually 1 for burn-after-read pastes; updated conditionally |
| scan_status | varchar(20) | Pending, clean, suspicious, blocked, or failed |
| status | varchar(20) | Active, deleted, expired, blocked, or burned |
| created_at | timestamp | Creation time for retention and audit |
| updated_at | timestamp | Last metadata or policy update |
| user_id | uuid | Primary key |
| varchar(320) | Unique login identity | |
| plan | varchar(32) | Free, paid, enterprise, or internal |
| created_at | timestamp | Account creation time |
| status | varchar(20) | Active, suspended, or deleted |
| paste_key | varchar(16) | Paste identifier for analytics aggregation |
| event_date | date | Daily bucket |
| views | bigint | Aggregated view count |
| unique_visitors_estimate | bigint | Approximate unique visitors from sketches |
| top_referrers | json | Small aggregate for dashboard display |
| event_id | uuid | Primary key for moderation and audit |
| paste_key | varchar(16) | Paste being scanned or actioned |
| event_type | varchar(40) | Created, scanned, flagged, blocked, appealed, or restored |
| reason | text | Policy or scanner reason |
| created_at | timestamp | Event time |
Indexes
- pastes.paste_key is the primary key and must support a single point lookup.
- pastes.owner_user_id, created_at supports account dashboards and deletion workflows.
- pastes.expires_at supports TTL cleanup, background sweeps, and lifecycle reporting.
- pastes.scan_status, updated_at helps scanners and moderators find pending or suspicious content.
- paste_views_daily.paste_key, event_date supports analytics dashboards.
- Do not index the full paste body. Use content hashes and external scanning systems for abuse workflows.
Relationships
A paste may belong to one user, but anonymous pastes have no owner. Analytics aggregates and abuse events reference paste_key and can be rebuilt or retained separately from the serving record. The read path should not join users, analytics, and abuse tables unless the paste is private or policy requires an access check.
NoSQL alternatives
A distributed key-value database such as DynamoDB, Cassandra, Bigtable, or FoundationDB fits the serving path because reads are point lookups by paste key. Keep small inline content below item-size limits and move larger bodies to object storage such as S3, Azure Blob Storage, or Google Cloud Storage.
Use conditional writes to reserve paste keys and atomic conditional updates to consume burn-after-read pastes. Store analytics in an append-friendly stream and OLAP store instead of updating the paste row on every view. Object storage lifecycle policies can expire large bodies after the metadata TTL passes.
High-Level Architecture
Public reads are served from CDN or cache when policy allows. The Paste API remains the source of truth for private, password-protected, one-time, expired, blocked, or cache-miss requests. Large bodies live in object storage, while metadata and small bodies stay in the serving database.
Pastebin has two serving modes. The common public read path should be extremely simple: edge cache if possible, then stateless Paste API, hot cache, metadata lookup, and optional object fetch. The create path performs validation, key allocation, persistence, and asynchronous scanning.
The design intentionally separates metadata from large content. Metadata is latency-sensitive and small enough for a key-value store or relational table. Large text bodies are byte-heavy and better suited for object storage with compression, lifecycle policies, and CDN integration.
Policy determines cacheability. Public, clean, non-password, non-burn pastes can use CDN and Redis TTLs. Private and burn-after-read pastes must bypass shared caches because each read requires authorization or an atomic state transition.
Request Flow
- 1
Create request arrives
The client sends POST /api/v1/pastes with text, optional language, visibility, expiration, burn-after-read flag, and optional password. The API authenticates if needed, validates size and TTL policy, normalizes line endings, and applies per-IP and per-user rate limits.
- 2
Paste key is allocated
For generated keys, the API requests a random base62 key from the Key Generation Service or generates one and performs a conditional insert. Custom keys, if offered, must be validated and inserted atomically to prevent races.
- 3
Content storage location is chosen
If the body is below the inline threshold, such as 32 KB or 64 KB, the service stores it in the paste row. Larger bodies are compressed, written to object storage, and referenced by object URI and content hash in metadata.
- 4
Metadata is committed
The service writes the paste metadata, visibility, TTL, password hash, scan status, content location, and initial status. Creation is acknowledged only after the metadata and any required object are durable.
- 5
Scanning and cache warming start
The API enqueues a scan job with content hash, metadata, and a safe pointer to the body. Low-risk public pastes may be served immediately with pending status, while high-risk or anonymous large pastes can remain limited until scanning completes.
- 6
Read request reaches edge or API
A browser requests GET /{pasteKey}. CDN serves cacheable public content if present. Otherwise the request goes to the Paste API, which loads the record from Redis or the metadata database.
- 7
Policy checks run before content is returned
The service checks existence, status, expiration, scan status, visibility, authentication, password verification, and burn-after-read state. For one-time pastes, it performs an atomic conditional update from remaining reads of 1 to 0 before returning the body.
- 8
Content is rendered or streamed
Inline content is returned directly from the record or cache. Large content is fetched from object storage, optionally cached at the edge if policy allows, escaped safely, and rendered with syntax highlighting or returned as raw text.
- 9
Analytics event is emitted asynchronously
After a successful read decision, the service emits a view event with paste key, timestamp, referrer, coarse geography, client type, and cache status. Analytics must not block the read response.
Core Components
Paste API Service
Owns create, read, policy checks, rendering, and raw text serving.
This stateless service validates inputs, chooses inline or object storage, enforces visibility and TTL, verifies passwords, consumes one-time reads atomically, escapes output, and emits analytics. It should keep slow dependencies behind timeouts and circuit breakers.
Key Generation Service
Produces compact unique paste keys with low collision risk.
The service generates random base62 keys, reserves them with conditional writes, and monitors collision rate. Random keys are preferred over sequential keys because unlisted pastes rely partly on key unguessability.
Metadata Store
Durable source of truth for paste metadata and small inline bodies.
The store is keyed by paste key and contains the policy fields needed to answer a read. It supports conditional writes for key reservation and conditional updates for burn-after-read consumption.
Object Storage
Stores large paste bodies outside the serving metadata record.
Large content is compressed and written to object storage. Object storage provides durable, inexpensive byte storage, lifecycle expiration, range reads for very large text, and CDN integration for cacheable public bodies.
Hot Paste Cache
Absorbs repeated reads for popular public pastes.
Redis or Memcached stores paste metadata and small inline bodies when policy allows. TTL is bounded by paste expiration and scan status, and private or one-time pastes should not use shared cache entries.
Abuse Scanner
Protects the platform from malicious or prohibited content.
The scanner checks content hashes, URLs inside pastes, malware signatures, spam patterns, leaked secrets, and policy rules. It updates metadata to clean, suspicious, or blocked and supports manual review workflows.
Analytics Pipeline
Captures view metrics without slowing reads.
View events go to a durable stream and are aggregated by paste key, time bucket, referrer, geography, and client class. Dashboards read aggregates, not the serving database or raw event stream.
Deep Dive
Inline content versus object storage
The central Pastebin tradeoff is where to store the text body. Inline storage is fast and simple for small pastes because a single cache or database lookup returns metadata and content. It also simplifies atomic creation and deletion.
Large inline bodies are dangerous. They inflate database storage, reduce cache efficiency, increase replication cost, and make hot rows expensive to move. A practical design sets an inline threshold such as 32 KB or 64 KB. Content above that threshold is compressed and stored in object storage, while the metadata row stores object URI, size, hash, and content location.
This differs from a URL shortener. A shortener stores a small redirect target and returns a Location header. Pastebin stores user content and must handle body size, rendering safety, object fetches, and content moderation.
Key generation and unguessability
Paste keys have two jobs: uniqueness and reasonable resistance to guessing. A sequential counter encoded as base62 is easy to implement, but it exposes creation volume and lets attackers enumerate unlisted pastes. That is a serious privacy issue because unlisted links are often treated as share-by-link resources.
Random base62 keys with enough length are the better default. Eight characters provide about 218 trillion combinations, which is far more than the expected number of active pastes. The create path can generate a candidate and perform a conditional insert, retrying on rare collisions. A pre-generated key pool also works if operational complexity is acceptable.
Custom aliases should be optional and subject to stricter validation. They are easier to guess, can impersonate brands or users, and require atomic reservation just like generated keys.
Expiration and burn-after-read consistency
Expiration can be enforced lazily on read by checking expires_at and returning 410 Gone when the deadline has passed. Background cleanup and object-storage lifecycle policies reclaim space later. Correctness should not depend on cleanup running exactly on time.
Burn-after-read is stricter. Two clients may request the same paste concurrently, so the service must consume the read atomically before returning content. Use a conditional update such as remaining reads equals 1 and status equals active, then set remaining reads to 0 and status to burned. Only the request that wins returns the body.
Do not cache burn-after-read content in a shared CDN or Redis entry. A stale cache hit would bypass the atomic consumption step and leak the paste multiple times.
Caching and CDN policy
Caching is safe only when the access policy is cache-safe. Public, clean, non-password, non-burn pastes with future expiration can be cached at CDN and Redis with TTL capped by the paste expiration time. Negative caching for unknown keys should be short to avoid hiding newly created pastes after replication delay.
Private, password-protected, pending-review, and one-time pastes should bypass public caches and usually use Cache-Control: private, no-store. For unlisted but public pastes, cacheability is a product decision: caching improves cost and latency, but shared caches must not expose analytics or owner metadata.
Hot viral pastes can become single-key hot spots. Mitigate with CDN, replicated cache entries, request coalescing on misses, compression, and serving large object bodies directly from edge caches when allowed.
Abuse scanning and rendering safety
A paste service can host phishing kits, malware snippets, stolen secrets, spam lists, and offensive content. The create path should apply rate limits, size limits, content hashes, deny lists, and lightweight synchronous checks. Heavier scanners run asynchronously and can mark a paste suspicious or blocked.
Rendering is also security-sensitive. Syntax highlighting must treat paste content as untrusted text, escape HTML, block script execution, and avoid storing unsafe highlighted HTML unless the sanitizer is trusted. Raw views should send text/plain and avoid content sniffing.
Scanner results affect cache invalidation. If a paste is later blocked, the system must evict CDN and Redis entries or maintain a small blocked-key cache checked before serving cached content.
Analytics without slowing reads
View analytics are useful, but the read path should not synchronously update a counter in the paste row. Popular pastes would create write hot spots, and analytics outages would become read outages.
Emit view events asynchronously after the policy decision. Consumers aggregate by paste key and time bucket, using approximate unique visitor sketches where needed. Product dashboards can tolerate eventual consistency and freshness indicators.
For privacy, avoid storing raw IP addresses longer than necessary. Prefer coarse geography, hashed or truncated identifiers, retention limits, and tenant-specific access controls for detailed analytics.
Scaling
Prototype: single region and relational database
Start with one stateless Paste API, one relational database table keyed by paste key, and local disk or basic object storage for large bodies. Add size limits, TTL checks, and safe rendering from the beginning.
Growth: cache, object storage, and async scanning
Move large bodies to object storage, introduce Redis for hot public pastes, add CDN for cacheable rendered and raw responses, and run scanning plus analytics through queues. Separate read and create autoscaling policies.
Large scale: distributed metadata store
Move the metadata table to a distributed KV store partitioned by paste key. Use conditional writes for key reservation and burn consumption, object lifecycle policies for TTL cleanup, hot-key detection, and per-tenant or per-IP quotas.
Global scale: regional reads and controlled writes
Route users to the nearest healthy region for reads. Replicate metadata and object pointers asynchronously, keep creates durable in a home region or multi-region database, and use global CDN invalidation for deletes, burns, expirations, and abuse takedowns.
Bottlenecks & Optimizations
Database bloat from storing every paste inline
Set an inline threshold and move large bodies to object storage. Store only metadata, object URI, hash, size, and policy fields in the database. Compress large content and apply lifecycle expiration.
Viral paste hot spot
Cache public clean pastes at CDN and Redis, replicate hot cache entries, use request coalescing on object-storage misses, and cap cache TTL by expiration and takedown policy.
One-time paste race condition
Consume burn-after-read pastes with an atomic conditional update before returning content. Bypass shared caches and return 410 Gone to concurrent readers that lose the condition.
Object storage latency for large content
Compress bodies, keep metadata in cache, use CDN for cache-safe objects, support range or streaming reads, and apply connection pooling plus retries with tight timeouts.
Synchronous scanner or analytics dependency
Run heavy scanning and all analytics asynchronously. Use lightweight synchronous checks for obvious abuse, and let safe reads continue when analytics is degraded.
Random key guessing and invalid-key scans
Use sufficiently long random keys, rate-limit 404-heavy clients, negative-cache invalid keys briefly, and monitor entropy or prefix scan patterns.
Failure Handling
Cache outage
The Paste API falls back to the metadata store and object storage with strict timeouts and rate limiting. Use circuit breakers to prevent stampedes, and gradually warm cache after recovery.
Metadata database degradation
Serve safe cached public pastes until their TTL expires, but block private and burn-after-read reads that require fresh policy checks. Pause creates if key reservation or metadata durability cannot be guaranteed.
Object storage unavailable
Small inline pastes can continue serving. Large pastes should return a retryable 503 or friendly error if the object cannot be read. Creates for large bodies can fail fast or queue uploads only if durability semantics are clear.
Scanner backlog or outage
Apply stricter rate limits to anonymous creates, keep known-bad signatures and deny lists cached, mark high-risk pastes as pending, and allow trusted low-risk pastes with delayed scanning. Alert on backlog age, not just queue depth.
Analytics pipeline unavailable
Continue serving reads. Buffer a bounded number of events locally or drop non-critical analytics under pressure, and show freshness warnings in dashboards. Never block paste reads on analytics recovery.
Stale cache after delete or takedown
Invalidate CDN and Redis entries on status changes, keep cache TTLs bounded, and maintain a small blocked-key or deleted-key cache checked before serving sensitive entries. Use synthetic probes for high-priority takedowns.
Security
Access control
Private pastes require authenticated authorization checks. Owners and privileged operators can delete, view analytics, or change policy. Public reads must not reveal owner email, private metadata, or moderation details.
Password protection
Store only strong salted password hashes, apply rate limits to password attempts, and avoid caching password-protected content in shared caches. Passwords protect the paste, not the underlying object URI, so object keys must remain private.
Abuse and malware scanning
Scan content, embedded URLs, hashes, and user reputation signals. Support blocking, warning pages, appeal workflows, and rapid cache invalidation for malicious or policy-violating pastes.
XSS and content sniffing prevention
Escape all paste content before rendering, use a hardened syntax highlighter, set safe content types for raw text, prevent browser content sniffing, and use a restrictive content security policy.
Rate limits and quotas
Apply per-IP, per-user, per-token, and per-tenant limits on creation, reads, password attempts, and invalid-key scans. Enforce content size limits and account-specific retention policy.
Privacy and analytics minimization
Limit raw event retention, store coarse geography instead of raw IP when possible, protect analytics behind ownership checks, and avoid indexing private or unlisted paste content in search engines.
Tradeoffs
Pros
- +Simple key-based read path that can be optimized with cache and CDN.
- +Inline small content keeps common reads fast and operationally simple.
- +Object storage for large content controls database growth and bandwidth cost.
- +Asynchronous scanning and analytics keep create and read latency predictable.
- +Random keys and TTL policies support safe unlisted sharing for a beginner design.
Cons
- −One-time and private pastes reduce cacheability and require stronger consistency.
- −Large content introduces object-storage latency, lifecycle coordination, and CDN invalidation complexity.
- −Abuse scanning can delay availability or require later takedowns after content was shared.
- −Unlisted links are not true authorization and can leak if the key is forwarded.
- −Exact real-time analytics can conflict with low-latency read serving.
Alternatives
Alternative one is to store all content in a relational database. It is easy for a prototype but becomes expensive and slow as large pastes accumulate.
Alternative two is to store every body in object storage, including tiny pastes. It simplifies database size but adds object fetch latency to the common case and complicates atomic creation.
Alternative three is a document-sharing system with full ACLs, collaboration, search, and versioning. It is more powerful but overbuilt for temporary snippets and anonymous sharing.
When not to use this design
Do not use Pastebin as a secure secret manager, source-control system, or long-term compliance archive. If the content is highly sensitive, needs strong identity-based access, version history, legal retention, or guaranteed deletion semantics, design a secure document store or secrets platform instead.
Follow-up Questions
What threshold should decide inline versus object storage?
Choose a threshold that keeps the metadata record small and cache-efficient, commonly 32 KB or 64 KB. The exact value depends on database item-size limits, p99 latency, cache memory, and average paste size. The key is to keep common small reads to one lookup while moving large byte-heavy content to object storage.
How do you make burn-after-read correct under concurrent reads?
Do an atomic conditional update before returning content. The update checks that status is active and remaining reads equals 1, then sets status to burned and remaining reads to 0. Only the request that wins the condition gets the body; all others return 410 Gone.
Can public pastes be cached at the CDN?
Yes, if they are public, clean, not password-protected, not private, not burn-after-read, and have a cache TTL no longer than their expiration. Private and one-time pastes must bypass shared caches because each read requires a fresh policy decision.
How is this different from designing a URL shortener?
Both systems generate short keys and are read-heavy, but URL shorteners store small redirect mappings and return HTTP redirects. Pastebin stores user content, serves bytes, manages large object storage, renders syntax highlighting safely, scans content for abuse, and enforces visibility or burn policies before returning the body.
Should the service scan synchronously or asynchronously?
Use lightweight synchronous checks for obvious abuse, size, known-bad hashes, and rate limits. Run heavier malware, spam, secret, and policy scanning asynchronously. High-risk content can remain pending until the scan finishes, while trusted low-risk content can be available quickly with takedown support.
How do you prevent unlisted paste enumeration?
Use long random keys, avoid sequential exposed IDs, rate-limit invalid-key scans, negative-cache repeated misses briefly, and detect prefix or distributed scanning patterns. Unlisted is convenience sharing, not strong authorization, so sensitive content should use private access controls.
Where should syntax highlighting happen?
For small or popular pastes, highlighting can be generated on read and cached as escaped rendered HTML if the sanitizer is trusted. For large or uncommon pastes, render on demand or client-side to avoid storing many variants. Raw text should always remain available and safely typed as text/plain.
Company Variations
Amazon
Amazon interviewers may push on DynamoDB partitioning, S3 object lifecycle, conditional writes for burn-after-read, operational alarms, and cost. Be ready to explain inline thresholds, object pointers, cache invalidation, and how public reads survive scanner or analytics failures.
Microsoft
Microsoft may frame the system around enterprise snippets, Azure Blob Storage, Azure Front Door, identity integration, tenant policy, compliance retention, and private sharing. Discuss access control, audit logs, password handling, and safe rendering inside corporate tools.
Google tends to probe global caching, tail latency, abuse detection, privacy, and consistency. Expect follow-ups on random key entropy, CDN cacheability, one-time read races, and large-object serving at edge scale.
Meta
Meta may emphasize abuse, spam, viral hot spots, content safety pipelines, and privacy for shared links. Explain how asynchronous review, takedowns, cache invalidation, and analytics aggregation work without coupling to the read path.
Interview Tips
Lead with the read path and the storage split. Say that most pastes are small and can be served quickly from cache or metadata, but large pastes must move to object storage. Then layer in policy: TTL, one-time reads, visibility, password checks, scanning, and analytics. Whenever you mention caching, immediately state which paste types are safe to cache and which must bypass shared caches.
What interviewers expect
- ✓State assumptions for paste count, average size, retention, read ratio, and peak traffic.
- ✓Use paste_key as the serving key and keep reads to cache or one metadata lookup plus optional object fetch.
- ✓Explain why small content can be inline and large content belongs in object storage.
- ✓Discuss TTL, burn-after-read atomicity, and visibility semantics clearly.
- ✓Add CDN, Redis, async analytics, abuse scanning, and safe syntax rendering.
- ✓Call out how this differs from URL shortener and cloud storage designs.
Common mistakes
- !Treating Pastebin as just a URL shortener and forgetting that it stores and serves content bytes.
- !Storing all large pastes inline in the primary database.
- !Caching private, password-protected, or burn-after-read pastes in shared caches.
- !Implementing burn-after-read with a non-atomic read then update.
- !Rendering user text without escaping or content security controls.
- !Updating analytics synchronously on every view.
Red flags
- ×No content size limits or inline versus object storage split.
- ×No concrete capacity math for content storage and read QPS.
- ×No plan for expiration, deletion, and cache invalidation.
- ×No abuse scanning or rate limiting for anonymous content creation.
- ×No distinction between public, unlisted, private, password, and one-time cache policy.
Revision Notes
- Pastebin stores and serves text content; it is not just a redirect mapping like URL Shortener.
- Use paste_key as the primary lookup key. A read should hit CDN, Redis, or one metadata lookup plus optional object fetch.
- Small pastes can be inline in the metadata database. Large pastes should be compressed in object storage with URI, hash, size, and policy in metadata.
- With 30M creates per month and 50:1 reads, expect about 12 write QPS average, 580 read QPS average, and 10x peaks around 120 writes and 5,800 reads per second.
- Twelve months of content at the assumed mix is about 30 TB raw before replication and lifecycle cleanup.
- Use long random base62 keys. Eight characters provide about 218T combinations and reduce enumeration risk.
- Cache only public, clean, non-password, non-burn pastes. TTL must not exceed expiration, and takedowns need invalidation.
- Burn-after-read requires an atomic conditional update before returning content.
- Scan content for spam, malware, secrets, and policy violations. Escape rendered output and serve raw text safely.
- Emit view analytics asynchronously and aggregate outside the serving database.
Flashcards
Quiz
0/7 answered
1.Why does Pastebin need object storage in addition to a metadata database?
2.Which paste type should not be served from a shared CDN cache?
3.Given 30M creates per month and 30 days per month, what is the approximate average write QPS?
4.What is the safest way to consume a one-time paste under concurrent reads?
5.Why are long random paste keys preferred for unlisted pastes?
6.Where should view analytics be processed?
7.What is the main security concern when rendering syntax-highlighted pastes?
Cheat Sheet
Goal: create text pastes, return compact keys, and serve content quickly while enforcing TTL, visibility, password, one-time read, and abuse policy.
Workload: 30M creates per month, 50:1 reads, about 12 write QPS average, about 580 read QPS average, and 10x peaks around 120 writes and 5,800 reads per second.
Storage split: small pastes inline in metadata for one lookup. Large pastes compressed in object storage with metadata pointer, size, hash, language, status, and TTL.
Key generation: random base62 keys with conditional insert. Eight characters gives about 218T combinations and helps resist enumeration.
Serving path: client to CDN for cacheable public reads. On miss or private policy, go to load balancer, Paste API, Redis, metadata DB, and object storage if needed.
Cache policy: cache public clean non-password non-burn pastes only. Cap TTL by expiration and invalidate on delete, burn, or takedown.
Burn-after-read: perform atomic conditional update before returning the body. Never serve through shared cache.
Security: escape rendered text, use safe raw content types, rate-limit creates and invalid scans, hash passwords, scan abuse, and protect private analytics.
Analytics: publish view events asynchronously and aggregate outside the serving database.
References
- BookSystem Design Interview — Alex Xu
- BookDesigning Data-Intensive Applications — Martin Kleppmann
- DocsAmazon S3 User Guide — Amazon Web Services
- DocsAmazon DynamoDB Developer Guide — Amazon Web Services
- DocsOWASP Cross Site Scripting Prevention Cheat Sheet — OWASP