04Case study
Uploadery
Cloud file hosting with signed delivery
- Year
- Role
- Status
- Live
- uploadery.com ↗
The obvious way to build file hosting is to accept the upload in your own handler and forward it on. It works until the first large file, at which point your web server is a very expensive, very slow pipe. Uploadery never touches the bytes.
- 0
- Bytes through the app server
- Pre-signed
- Both directions of transfer
- Metadata
- All the database ever holds
The constraint
What made it hard
Proxying uploads through the application means every concurrent transfer occupies a request handler for its full duration, buffers into memory or a temp disk, and runs against the platform’s request body limits and timeouts. Egress is paid twice - once into the server, once out of it. The failure mode is unpleasant too: the connection dies mid-file and there is a half-written object and no clean way to resume.
Approach
01
The server issues permission, not bandwidth
A client asks for an upload slot; the application authenticates it, decides whether that user may write, and returns a short-lived pre-signed S3 URL. The browser then talks to S3 directly. The application has done its job before a single byte moves.
02
Reads are signed the same way
Downloads are short-expiry signed GETs rather than public objects. Access control lives in the decision to issue a URL, so a leaked link stops working on its own instead of exposing a permanently public bucket path.
03
Derivatives generated on ingest
Images are optimised and resized once, on arrival, and the variants are stored alongside the original - so serving a thumbnail is a static fetch rather than a transformation on every request.
04
The database describes files, it does not store them
Prisma models hold owner, key, size, content type and timestamps. That keeps rows small and queries fast, and means a storage migration is a key rewrite rather than a data export.
Architecture
Specification
- Transfer
- Auth
- Storage
- Metadata
- Images
Stack
- Next.js
- React
- Prisma
- PostgreSQL
- AWS S3
- NextAuth
- Tailwind CSS
Where it landed
01
Large uploads are limited by the user’s connection, not by a request timeout.
02
Hosting cost scales with storage rather than with server time spent shovelling bytes.
03
A shared link expires by itself; nothing in the bucket is ever publicly readable.
Next case study
05
Paywallio
Content monetisation and gated access
Something that has towork in production?
I take on contract engineering and full-time roles. Most useful first message: what you are building, what is currently in the way, and when you need it live.