Blog
4 min read

What Is Object Storage? S3, Buckets, and Where Your Files Should Live

Object storage keeps files as objects in buckets, reachable over HTTP — Amazon S3 is the original, and dozens of services speak the same API. How it differs from a hard disk, what buckets, keys and presigned URLs are, what it costs, and when your app needs it.

When your app lets users upload a profile photo, a PDF or a video, those files have to live somewhere. The usual answer is object storage — and the name you'll hear most is S3, Amazon's service that started it all.

What it is

Object storage is a service that stores files ("objects") inside containers called buckets, and lets you read and write them over HTTP.

  • A bucket is like a top-level folder: myapp-uploads.
  • Each object has a key — its name, which can look like a path: users/42/avatar.jpg.
  • Each object can have metadata: content type, size, custom tags.

There aren't really folders. users/42/avatar.jpg is just one long name; tools display the slashes as folders for convenience.

How it's different from a disk

A server's disk Object storage
Accessed via The file system HTTP API
Capacity Fixed, you resize it Practically unlimited
Shared between servers No (usually) Yes
Edit part of a file Yes No — replace the whole object
Survives server rebuilds Not always Yes
Serve directly to browsers Through your app Yes, via URLs
Cost Included in the server Per GB stored + data transferred out

The key advantage: storage is separate from your app. You can redeploy, add servers or move hosts and the files stay put. That's why apps on serverless platforms — where the disk vanishes after each request — must use object storage for uploads. (Where should user uploads go?)

"S3-compatible"

Amazon S3's API became the standard. Many providers speak it, so the same code and libraries work against all of them:

  • Amazon S3
  • Cloudflare R2 (no fees for data transfer out)
  • Backblaze B2
  • Hetzner, DigitalOcean Spaces, Wasabi
  • Supabase Storage (with an S3-compatible endpoint)
  • MinIO and similar (self-hosted)

You change an endpoint URL and keys, not your code.

Public vs private

Buckets are private by default, and they should usually stay that way. Two ways to give access:

  • Public objects — fine for things everyone may see, like product images. Often served through a CDN. (What is a CDN?)
  • Presigned URLs — your server generates a temporary link (say, valid for 10 minutes) to a private object. Used for private downloads and for letting browsers upload directly without going through your server. (Presigned URLs for direct uploads)

Accidentally public buckets are one of the most common causes of data leaks. Never make a bucket containing user documents public "to make it work."

What it costs

Usually three parts:

  1. Storage — per GB per month. Cheap: a few cents per GB or less.
  2. Requests — tiny charges per thousand reads/writes.
  3. Egress — data sent out to the internet. This is where bills surprise people with traffic-heavy files like video. Some providers (like R2) charge nothing for it.

Using it from code

With the AWS SDK (which works for most S3-compatible providers):

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'

const s3 = new S3Client({
  region: 'auto',
  endpoint: process.env.S3_ENDPOINT,
  credentials: {
    accessKeyId: process.env.S3_KEY,
    secretAccessKey: process.env.S3_SECRET,
  },
})

await s3.send(new PutObjectCommand({
  Bucket: 'myapp-uploads',
  Key: `users/${userId}/avatar.jpg`,
  Body: fileBuffer,
  ContentType: 'image/jpeg',
}))

Keep the keys on the server — never in frontend code. (Hide API keys)

Good practices

  • Store the object key in your database, not the full URL — easier to change providers or CDNs later.
  • Validate file type and size before accepting uploads.
  • Use random or ID-based keys, not user-supplied file names.
  • Set lifecycle rules to delete temporary files automatically.
  • Object storage is also a great place for database backups — off the server they're protecting. (Backups for beginners)

The summary

  • Object storage keeps files in buckets, accessed over HTTP.
  • It's separate from your server, so files survive redeploys and are shared across servers.
  • The S3 API is the standard; many providers are compatible.
  • Keep buckets private; use presigned URLs for temporary access.
  • Watch egress costs on traffic-heavy files.

EasySpawn offers S3-compatible bucket storage as an add-on alongside your servers, so uploads and backups live off the machine with a predictable monthly price. See pricing or join the waitlist.

Related: Where Should User Uploads Go? · Direct-to-Storage Uploads With Presigned URLs · Backups for Beginners · What Is a CDN?

Keep reading