Large blobs — presign, direct upload, multipart, events, CDN

Handling large blobs for system design interviews

Move videos and documents off your API path: presigned uploads, CDN signed downloads, multipart resume, event-driven state sync, and when not to use direct-to-storage — with interview scenarios for YouTube, Instagram, and Dropbox.

Why large files need their own pattern

Large files — videos, images, documents — need special handling. Instead of shoving gigabytes through your servers, use presigned URLs so clients upload directly to blob storage and download from CDNs. You get resumable uploads, parallel transfers, and progress tracking — the stuff that separates real systems from toy projects.

This is the deep dive behind Common patterns. Pair with Managing long-running tasks (transcode after upload), Real-time updates (progress %), and Networking essentials (HTTP range requests).

01Presign

Scoped temp credentials.

02Direct

Client ↔ storage.

03Resume

Multipart chunks.

04Sync

Events + reconciliation.

Instagram photo pipeline, Dropbox sync, and YouTube transcode — all use presigned direct upload.
Problem Breakdowns — same pattern, different downstream workers.
Client requests presigned URL via API; transfers 2GB directly to blob storage.
Large Blobs — control plane auth, data plane direct.

The problem

If you've studied for system design interviews, you know large files belong in blob storage like S3, not databases. Databases excel at structured data with complex queries but are terrible with large binary objects. A 100MB BLOB kills query performance, backup times, and replication. Object stores are built for this: unlimited capacity, 11-nines durability, per-object pricing. Rule of thumb: over 10MB and no SQL queries needed → blob storage.

Blob storage solved storage but not transfer. The naive approach routes bytes through application servers: client uploads 2GB video → API receives → forwards to S3. Downloads reverse the path. Works for small files; breaks as files grow.

Client uploads and downloads 2GB through App Server proxy to blob storage.
Server as a Proxy — dumb pipes add latency and cost.

We're forcing servers to be dumb pipes — they add no value, just latency and cost. Cloud providers already have global infrastructure, resume capability, and massive bandwidth. Yet we insert limited app servers as middlemen.

Serverless data access

Instead of proxying data, give clients temporary scoped credentials. Your server's role shifts from data transfer to access control — validate the request, generate credentials, get out of the way.

AWS S3, Google Cloud Storage, and Azure Blob Storage all support temporary URLs with time-limited upload or download permissions. CDNs validate signed tokens before serving content too.

Client gets presigned URL from app server then uploads directly to blob storage.
Serverless Data Access — validate once, transfer direct.

Simple direct upload

When a client wants to upload, your server receives a permission request — not the file. Validate the user, check quotas, generate a temporary upload URL. The URL encodes permission to upload one specific object to one location for a limited time (typically 15 minutes to 1 hour). This is a presigned URL.

Generating a presigned URL happens in your application's memory — no network call to storage. Your server uses cloud credentials to create a signature the storage service verifies later:

https://mybucket.s3.amazonaws.com/uploads/user123/video.mp4
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20240115%2Fus-east-1%2Fs3%2Faws4_request
&X-Amz-Date=20240115T000000Z
&X-Amz-Expires=900
&X-Amz-SignedHeaders=host
&X-Amz-Signature=b2754f5b1c9d7c4b8d4f6e9a1b2c3d4e5f6...

The signature is a cryptographic hash of request details (HTTP method, path, expiry) plus your secret key. Storage recalculates the hash — if it matches and hasn't expired, upload proceeds.

Encode restrictions when generating URLs — baked into the signature:

  • content-length-range — min/max sizes (prevent 10GB on a 10MB URL)
  • content-type — profile picture endpoint accepts images only

The client performs a simple HTTP PUT to the URL. From their perspective they're uploading directly to storage. Your infrastructure never touches the bytes. A Sydney user uploads to Sydney's region at full speed while your Virginia servers handle other requests.

Client requests presigned URL from app server then PUTs file directly to S3.
Simple Direct Upload — sign in memory, transfer direct.

Simple direct download

Downloads work the same way — from blob storage directly or through a CDN. Generate signed URLs granting temporary read access. Direct blob access is simpler and cheaper for infrequent downloads. CDN distribution costs more but gives better performance for hot content via geographic caching.

For CDN delivery you're not signing S3 URLs — you create CloudFront signed URLs or signed cookies the CDN validates:

https://d123456.cloudfront.net/videos/lecture.mp4
?Expires=1705305600
&Signature=j1k2l3m4n5o6...
&Key-Pair-Id=APKAIOSFODNN7EXAMPLE

Both use signatures, but validation differs:

  • Blob storage (S3 presigned) — validated by storage using your cloud credentials (shared secret).
  • CDN (CloudFront signed) — validated at edge using public/private key crypto. CDN holds the public key; you sign with the private key. No callback to origin needed.
Client gets signed URL from server; download via CloudFront CDN or direct from S3.
Simple Direct Download — CDN for hot content, direct for cold.

Resumable uploads

A 5GB video at 100 Mbps takes ~7 minutes. Connection drop at 99% with a simple PUT means starting over. All major clouds solve this with chunked upload APIs.

  • AWS S3 — multipart upload, 5MB–5GB parts, each with its own presigned URL
  • Google Cloud — resumable upload session URL + range headers
  • Azure — block blobs, 4MB–100MB blocks

Client uploads parts, tracking checksums. Connection drops after 60 of 100 parts? Query which parts succeeded (ListParts in S3), resume from part 61. Storage maintains state via upload ID / session URL.

Multipart upload with parts 1-12 complete and resume from part 13.
Resumable Uploads — only re-upload failed chunks.

Progress tracking comes naturally — percentage = completed parts / total. After all parts upload, call the completion endpoint with part numbers and checksums. Until completion succeeds, parts exist but no accessible file. Incomplete multipart uploads cost money — lifecycle rules should clean them up after 24–48 hours.

State synchronization

Moving servers out of the critical path solves the bottleneck but introduces distributed state management. Store metadata in your database; actual file lives in blob storage.

CREATE TABLE files (
    id              UUID PRIMARY KEY,
    user_id         UUID NOT NULL,
    filename        VARCHAR(255),
    size_bytes      BIGINT,
    content_type    VARCHAR(100),
    storage_key     VARCHAR(500),  -- s3://bucket/user123/files/abc.pdf
    status          VARCHAR(50),   -- pending, uploading, completed, failed
    created_at      TIMESTAMP,
    updated_at      TIMESTAMP
);

With direct uploads, keeping status in sync is tricky. The naive approach: client calls "upload complete!" after PUT. Problems:

  • Race conditions — DB shows completed before file exists
  • Orphaned files — client crashes after upload, before notify
  • Malicious clients — mark complete without uploading
  • Network failures — completion notification never arrives

Most blob storage services solve this with event notifications. When S3 receives a file, it publishes via SNS/SQS/Lambda with the object key — the same storage_key you stored when generating the presigned URL.

S3 ObjectCreated event through SNS to worker updating database status.
Event Notifications — storage confirms, not the client.

Events can fail too — add reconciliation as a safety net. A periodic job checks files stuck in pending and verifies against storage. Events as primary mechanism, reconciliation for stragglers.

Cron job queries pending rows in Postgres and verifies object existence in S3.
Reconciliation — safety net when events are delayed or lost.
files table in Postgres linked by storage_key to blob object.
Metadata — create pending row when minting URL; events flip status.

Cloud provider terminology

Each provider names the same concepts differently. You don't need SDK function names in interviews — understand the ideas. This table answers "what's the equivalent in X?"

FeatureAWSGoogle CloudAzure
Temporary upload URLsPresigned URLs (PUT/POST)Signed URLs (resumable/simple)SAS tokens
Multipart uploadsMultipart Upload (5MB–5GB parts)Resumable UploadsBlock Blobs (4MB–100MB)
Event notificationsS3 Events → Lambda/SQS/SNSCloud Storage Pub/SubEvent Grid
CDN signed URLsCloudFront signed URLs/cookiesCloud CDN signed URLsAzure CDN + SAS
Cleanup policiesLifecycle RulesLifecycle ManagementLifecycle Management Policies

When to use in interviews

Rule is simple: files larger than ~10MB through your API → this pattern immediately. Exact threshold depends on infrastructure; 10MB is where pain becomes real.

Common scenarios

  • YouTube / video — presigned S3 upload + multipart; S3 events trigger transcode; CloudFront serves segments with signed URLs.
  • Instagram / photos — mobile gets presigned URLs for 50MB+ originals; events trigger thumbnail/filter workers.
  • Dropbox / file sync — chunked presigned uploads; time-limited signed share links without recipient accounts.
  • WhatsApp / chat media — upload direct to storage; chat passes file reference; signed download URLs expire.

When NOT to use

  • Small files (<10MB) — normal API endpoints; presign adds latency for no benefit.
  • Synchronous validation — CSV import needing header validation before accept → must proxy bytes.
  • Compliance inspection — data must pass certified scanners (PCI, HIPAA) before storage.
  • Instant content feedback — face detection on profile photo during upload breaks async UX.

Common deep dives

What if upload fails at 99%?

Use chunked uploads for files over 10MB. Client queries which parts succeeded (ListParts / session status / committed blocks). Resume from the first failed part. Store session ID in localStorage for app-restart resume. Set lifecycle policies — incomplete parts cost money.

How do you prevent abuse?

Don't let users immediately access uploads. Quarantine bucket first — virus scan, content validation, type checks — then move to public bucket and set status "available." Include file size limits in presigned URL conditions. Processing delay naturally throttles automation.

Upload to quarantine bucket, scan worker validates, then move to public bucket.
Quarantine Pipeline — no public access until scan passes.

How do you handle metadata?

Rich metadata lives in your database, not object tags. Create DB record with status pending when generating presigned URL — includes storage_key. Use consistent key pattern like uploads/{user_id}/{timestamp}/{uuid}. Never let clients specify their own keys. Events include the key to find the exact row.

How do you ensure downloads are fast?

Serve through CDN with signed URLs. First user pulls from origin; subsequent users in-region get cached copies at single-digit ms latency. For large files, enable HTTP range requests for resumable downloads. Pragmatic approach: CDN + range support; let browser/download manager optimize. Parallel chunk downloads are rarely worth the complexity.

Client requests byte ranges from CloudFront for resumable large file download.
Resumable Download — HTTP Range requests for large files.

Cost and performance levers

Interview Q&A by level

Practice saying these out loud for large blob storage. Interviewers grade clarity and judgment more than buzzwords.

Interview takeaway

Match depth to the bar: define → trade off → operate. Don't dump principal answers in an entry-level screen.

Conclusion

Large blob handling appears in almost every user-generated content interview. When you hear "video uploads," "file sharing," or "photo storage," think bypassing servers for data transfer. Shift from moving bytes through infrastructure to orchestrating permissions and managing distributed state.

Demonstrate you understand both performance benefits and complexity trade-offs. Know when to use direct uploads (over 10MB) and when not to (small files, compliance). State synchronization is where many candidates stumble — events plus reconciliation is the answer.

Interview takeaway

Control plane mints presigned URLs; data plane ships gigabytes straight to blob storage — never through your app servers.

Related: Common patterns · Design Dropbox · Managing long-running tasks · Scaling reads (CDN).

Blob ops scenario: wedding album upload

← Lattice