Vetora logo
Easy6 componentsInterview: Medium

Pastebin — Text Sharing Service

Design a text sharing service handling 1M pastes/day with sub-200ms read latency. Covers cache-aside patterns, TTL-based expiration, PostgreSQL TOAST, and read-heavy optimization with Redis.

CachingStorageRead-Heavy
Problem Statement

Pastebin is a popular system design interview question because it appears simple on the surface — users paste text, receive a URL, and others can view it — yet the design space expands significantly when you consider scale, durability, and performance requirements. The problem tests a candidate's ability to reason about read-heavy workloads, caching strategies, and content storage trade-offs without the added complexity of real-time processing or distributed transactions. It serves as an excellent warm-up problem for system design rounds and is frequently asked at companies that value practical engineering judgment over theoretical complexity.

At production scale, a Pastebin-like service (such as GitHub Gists, Hastebin, or Pastebin.com itself) ingests roughly 1 million new pastes per day while serving 10 million paste views. This 10:1 read-to-write ratio is the defining characteristic that shapes every architectural decision. Most pastes are small text snippets averaging 5KB, but the system must handle outliers up to 10MB — code dumps, log files, and configuration exports. Read latency must remain under 200ms at p99 to feel instantaneous to users sharing code snippets in real-time conversations.

Beyond basic CRUD, the system must support configurable TTL (from 10 minutes to indefinite), optional password protection for private pastes, syntax highlighting hints, and URL-safe non-guessable identifiers to prevent enumeration attacks. Expired paste cleanup must happen reliably without impacting read performance, and the storage layer must handle years of accumulated data without degradation. Interviewers use this problem to assess whether candidates can identify the right caching strategy for a given access pattern, understand when a relational database is sufficient versus when object storage is needed, and reason about data lifecycle management at scale.

Architecture Overview

The Pastebin architecture follows a classic cache-aside pattern optimized for a 10:1 read-to-write ratio. Traffic enters through an API Gateway that handles JWT authentication, request validation, and rate limiting at 8,000 RPS with headroom above the 5,000 RPS peak. The gateway routes all requests to an Application Load Balancer, which distributes traffic across multiple PasteService pods running on ECS Fargate. Each pod runs 100 threads across 4 instances, providing 80K sustained RPS capacity — well above the peak load.

For write operations, PasteService generates a UUID-based identifier (Base62-encoded for URL friendliness), validates the content and optional metadata (TTL, syntax hint, password), persists the paste to PostgreSQL, and immediately writes it to Redis for read availability. PostgreSQL serves as the durable store with a pastes table indexed by paste_id, using TOAST to transparently compress and store larger pastes exceeding 8KB. Two read replicas handle cache-miss traffic without burdening the primary.

For read operations, PasteService checks Redis first. With a 90% cache hit rate, the vast majority of reads complete in approximately 2ms from cache. On a cache miss (10% of reads), PasteService queries PostgreSQL (approximately 12ms for an indexed read), checks whether the paste has expired, writes the result back to Redis, and returns it to the user. Redis entries carry a TTL matching the paste's expiration, so expired pastes auto-evict from cache without explicit invalidation.

A background cleanup job runs nightly to purge expired rows from PostgreSQL, preventing storage bloat. Since PostgreSQL lacks native TTL-based row deletion (unlike DynamoDB or Cassandra), this maintenance task is essential. The architecture deliberately omits a CDN because Pastebin access patterns follow a long tail — most pastes have a small audience, making CDN cache hit rates low and Redis cache-aside more cost-effective.

Architecture Preview
Loading architecture preview...
Key Design Decisions
Storage Engine

Choice

PostgreSQL with TOAST for all paste content

Rationale

At 5KB average paste size, PostgreSQL handles content storage efficiently without the operational overhead of a separate object storage system. TOAST transparently compresses and stores pastes exceeding 8KB, eliminating the need for a two-tier architecture (metadata DB plus S3). This simplicity reduces deployment complexity and operational burden for a moderate-scale service.

Caching Strategy

Choice

Redis cache-aside with LRU eviction and paste-TTL-aligned expiry

Rationale

The 10:1 read-to-write ratio makes caching essential. At 4,500 peak reads per second, serving all reads from PostgreSQL would require numerous read replicas. Redis cache-aside with a 90% hit rate reduces database reads to approximately 450 per second, easily handled by a single primary with two replicas. Aligning Redis TTL with paste expiry ensures expired pastes auto-evict without invalidation logic.

Identifier Generation

Choice

UUID-based identifiers with Base62 encoding

Rationale

Sequential IDs allow enumeration attacks where an attacker can scrape all pastes by incrementing the identifier. UUID-based IDs encoded in Base62 are non-guessable, providing security by obscurity for unlisted pastes without requiring authentication for viewing. Base62 encoding keeps URLs compact and human-readable compared to raw UUIDs.

Expiration Management

Choice

Dual-layer TTL with background cleanup

Rationale

Redis TTL handles cache-level expiration automatically, ensuring expired pastes are not served from cache. PostgreSQL rows are cleaned up by a nightly background job that deletes pastes past their expires_at timestamp. This dual-layer approach ensures correctness on reads (expired pastes return 404 immediately) while deferring the expensive bulk-delete operation to off-peak hours.

Scale & Performance

Target RPS

5,000 peak (4,500 reads + 500 writes)

Latency (p99)

<200ms p99 (reads); <500ms p99 (writes)

Storage

~2 TB/year before expiry cleanup

Availability

99.9%

This template is for educational and illustration purposes only. It may not represent the optimal production design for this problem. Real-world systems involve additional considerations (compliance, specific cloud provider constraints, organizational requirements) not captured here. Use this as a starting point for discussion, not as a production blueprint.

Frequently Asked Questions
Why use PostgreSQL instead of S3 for storing paste content?

PostgreSQL is the simpler choice when average paste size is small (5KB). S3 adds operational complexity — a separate storage system to manage, eventual consistency concerns, and higher per-request latency for small objects. PostgreSQL's TOAST mechanism transparently compresses and stores larger pastes exceeding 8KB without application-level changes. For a service where the maximum paste size is 10MB and the average is 5KB, a single-system approach (RDBMS for both metadata and content) reduces deployment complexity and eliminates the need for two-phase writes across separate storage backends.

How does cache-aside differ from write-through caching for a Pastebin?

In cache-aside, the application checks the cache first on reads and populates it on misses from the database. In write-through, every write goes to both the cache and the database simultaneously. Pastebin uses cache-aside because it naturally handles the hot-set problem: only frequently accessed pastes remain in cache via LRU eviction, while cold pastes are evicted and served from the database on the rare occasion they are requested. Write-through would waste cache memory by storing every new paste regardless of whether it will ever be read again.

How do you prevent URL enumeration attacks on a Pastebin service?

Sequential or short numeric IDs allow attackers to iterate through all possible paste URLs and scrape content. Using UUID-based identifiers encoded in Base62 produces 22-character URL-safe strings with an astronomically large keyspace (approximately 3.4 x 10^38 possibilities). This makes brute-force enumeration computationally infeasible. For additional protection, password-protected pastes require a separate authentication step before revealing content, and rate limiting at the API gateway throttles rapid sequential requests from a single IP.

How does a Pastebin handle paste expiration at scale?

Expiration is handled at two layers. At the cache layer, each Redis entry carries a TTL matching the paste's configured expiration time, so expired pastes are automatically evicted without explicit invalidation. At the database layer, the PasteService checks the expires_at column on every read and returns a 404 for expired pastes even if the row still exists. A nightly background cleanup job bulk-deletes expired rows from PostgreSQL to reclaim storage. This separation ensures users never see expired content while deferring the expensive deletion work to off-peak hours.

When should you add a CDN to a Pastebin architecture?

A CDN is beneficial when a small number of items receive a disproportionately large share of traffic — viral content, popular landing pages, or static assets. Pastebin traffic follows a long-tail distribution: most pastes are shared among a small group (a team, a few friends) and rarely go viral. This means CDN cache hit rates would be low, making the CDN cost-ineffective compared to a Redis cache-aside layer that naturally retains the hot working set. A CDN becomes worthwhile if the service evolves to support public galleries, trending pastes, or embedded code snippets that receive broad traffic.

Related Templates

Discussion

Sign in to join the discussion.

Ready to design your own Pastebin?

Open the simulator, place components on the canvas, wire them up, and run a traffic simulation to see how your architecture performs under real load.

Open Simulator