Object storage for user uploads: stop filling your server's disk
Every app eventually accepts a file: an avatar, a PDF invoice, a product photo. The natural first instinct is to write it to a folder on the server — and that instinct is exactly what fills your disk, breaks your deploys and blocks your scaling. Avatars, PDFs and images don't belong on your app server's disk. A Nest Storage bucket makes them durable, cheap and CDN-friendly, and this guide shows you how to get there.
Why local disk fails you
A folder full of uploads works fine right up until it doesn't. Disks fill up silently in the background, and the first symptom is usually your database or your logs failing because the uploads folder ate the last gigabyte. Worse, many deploy setups replace the entire release directory — one deploy, and every file your users trusted you with is gone.
Then there's scaling. The moment you add a second server behind a load balancer, half your requests land on a machine that doesn't have the file. Sticky sessions and rsync hacks only postpone the problem. Files that live on one machine's disk are, by definition, a single point of failure.
The upload flow that works
The pattern is simple: the client sends the file to your API (or straight to the bucket with a presigned URL), your API pushes it into a Nest Storage bucket, and the bucket hands back an object key. That key — not the file — is what you store in your database.
Your database stays small and fast, your servers stay stateless, and the file itself lives somewhere built for durability. Here's the whole flow in two lines:
const { key } = await nest.upload("avatars", file);
await db.user.update({ id, avatarKey: key });Private vs public buckets
Not every file deserves the same treatment. Logos, product images and other site assets can live in a public bucket and be served directly — ideally through a CDN with a custom domain. Anyone can read them, and that's the point.
User documents are different. Invoices, contracts and ID uploads belong in a private bucket, and your API grants access by generating signed URLs that expire after a few minutes. The file is never publicly reachable; only the link you just minted is.
- Public bucket for images and static assets
- Private bucket plus expiring signed URLs for documents
- Separate buckets per environment, so staging can never touch production files
Naming, versioning and cleanup
Object keys are your filing system, so choose prefixes deliberately: avatars/{userId}/… or invoices/2026/04/… make files easy to list, migrate and delete per user or per date. A nest:// URI with a clean key structure is self-documenting.
Turn on versioning for buckets where an accidental overwrite would hurt — an old version is one API call away instead of gone forever. And add lifecycle rules to sweep up orphaned files: uploads whose database row was deleted, or temp files older than a week, get cleaned up automatically instead of costing you money forever.
What it costs
With Nest Storage you pay for two things only: the storage you actually use and the bandwidth you actually serve. There's no per-request nickel-and-diming and no surprise line items — pricing is in ₹, predictable, and easy to reason about before you commit.
There's a free tier generous enough for side projects, so the avatar upload feature you build this weekend costs nothing until real users show up. When they do, the same bucket, the same API and the same keys keep working — just with a bigger quota.
Ready to put it into practice?
Spin up a server, a database or a bucket — free tiers included.