Daniel Howells

Zero Local Storage

2025-07-25

A pattern has emerged across my recent projects: zero local storage dependency. Managed object storage for files, Neon for the database, Vercel for compute. The development environment needs Node.js and a .env file. No Docker containers, no local Postgres instance, no filesystem state to manage. Clone the repo, install dependencies, run the dev server. That's it.

The DX improvement is significant and compounding. No "works on my machine" debugging when the local Postgres version doesn't match production. No Docker daemon eating 4GB of RAM in the background. No disk space surprises from accumulated uploads in a local storage directory. No migration conflicts from stale local database state. Every developer hits the same Neon branch, the same managed storage project, the same infrastructure. Environment parity isn't aspirational -- it's structural. The development database is a Neon branch, which means it's running the same Postgres version, extensions, and configuration as production.

The file handling is where this pattern pays off most. Tensile, Faceplacer, Popular Archive -- all of them upload directly to managed storage without touching the local filesystem. An image upload is a function call that returns a URL. That URL goes into the database. There's no filesystem path to manage, no cleanup cron job, no storage volume to provision. CDN distribution is automatic. Image transformations happen at the edge. The conceptual model is simpler too: images are just URLs. Your database stores strings, not files. Backups are database backups, not database-plus-filesystem backups.

The one edge case that still needs local storage: development seed data. When you're building features that depend on having 500 products with images in the database, you don't want to re-upload 500 images to managed storage every time you reset your development branch. I keep a seed script that references already-uploaded URLs from a shared development storage bucket. The URLs are stable, the seed is fast, and the local filesystem stays clean. It's a small compromise in an otherwise zero-local-state architecture, and it's the only place where the pattern bends. For everything else -- files, data, compute -- the cloud handles it and the local machine stays lightweight.