Object storage
A bucket you throw files into by key and fetch back by URL. No folders, no filesystem, just cheap storage that grows as you fill it.
See it
What it is
Object storage is a bucket you write files into by key and read back by key or URL. There is no real filesystem underneath: no directories, no partial writes, no renaming. A key like 'uploads/42/avatar.png' just looks like a path because slashes are allowed in names. Capacity is elastic: you keep writing and the provider keeps taking it, within whatever quotas, request limits, and billing you actually agreed to. S3 defined the shape, and Cloudflare R2, Backblaze B2, and MinIO expose S3-compatible APIs, so the same SDK usually works with a changed endpoint. Google Cloud Storage and Azure Blob Storage share the model but speak their own APIs (GCS also offers an S3-style interoperability mode), so 'S3-compatible' is a feature to check, not a given.
Reach for it for anything big and binary: user uploads, images, video, PDFs, backups, build artifacts, logs. The standard pattern is that your database stores only the key plus metadata (size, type, owner) while the bytes live in the bucket, uploads go straight from browser to bucket via a presigned URL, and a CDN sits in front for reads. Never stuff a 4MB image into a database column because it was easier.
Gotchas: buckets get left public by accident, which is how private customer files end up indexed by Google. Egress can cost more than storage on some providers (R2 charges zero egress, which is most of why people move to it). And a rename is really a copy plus a delete, so reorganizing a million keys is a real job, not a quick fix.
Ask AI for it
Move user file uploads off the app server onto object storage, using an S3-compatible provider (S3, R2, B2, MinIO) so one SDK covers them, or the provider's own SDK if we are on GCS or Azure Blob. Backend exposes an endpoint that validates content type and size then returns a presigned PUT URL, so the browser uploads directly to the bucket and never proxies bytes through my server. Use the key pattern 'uploads/{userId}/{uuid}.{ext}', store only key, mime type, size, and owner in the database, keep the bucket fully private, and serve reads through short-lived presigned GET URLs. Add a lifecycle rule that deletes objects under 'tmp/' after 24 hours.