Skip to content
AWS aws storage 5 min read

Objects, Keys & Prefixes

Amazon S3 (Simple Storage Service, AWS’s object storage service) stores your data as objects inside buckets. The Console shows those objects sitting inside neat folders, which makes S3 feel like a regular file system. It is not. Under the hood, S3 is a flat key-value store with no real directories at all. Understanding what an object, a key, and a prefix actually are will save you from listing bugs, broken lifecycle rules, and accidentally slow designs.

What an object actually is

An S3 object is a single piece of stored data plus information about that data. Every object has three parts:

  • Data (the body) — the bytes you uploaded: an image, a video, a JSON file, a backup, anything up to 5 TB.
  • Key — the full, unique name of the object within the bucket (more on this below).
  • Metadata — key-value pairs describing the object. Some is system metadata (like Content-Type, Last-Modified, size, and storage class). Some is custom metadata you set yourself (headers prefixed with x-amz-meta-).

You always retrieve an object by its key. There is no way to “open a folder and look inside” at the storage layer, because folders do not exist there.

What a key is

The key is the complete name of an object inside a bucket. It is just a string, and it is unique within that bucket. A key can be up to 1,024 bytes of UTF-8 characters and may contain slashes (/), but the slashes carry no special meaning to S3 — they are ordinary characters in the name.

So this key:

invoices/2026/06/inv-1042.pdf

is not a file called inv-1042.pdf living three folders deep. It is a single object whose entire name happens to be invoices/2026/06/inv-1042.pdf. The bucket has no invoices folder and no 2026 folder. There is only one flat list of keys.

The bucket name plus the key form the object’s address. The S3 URI is s3://my-bucket/invoices/2026/06/inv-1042.pdf. There is nothing between the bucket and the full key.

What a prefix is, and why folders are an illusion

A prefix is simply the leading part of a key up to a chosen delimiter — almost always the / character. When you ask the Console (or the CLI) to “list a folder,” what really happens is:

  1. S3 scans all keys in the bucket.
  2. It groups keys that share the same prefix up to the next /.
  3. The Console draws each unique prefix as a folder icon.

That is the entire trick. The “folder” invoices/2026/ is just every key that starts with the string invoices/2026/. Delete every object under it and the folder vanishes, because it was never a real thing — it was a visual summary of matching prefixes.

Listing with a delimiter

The CLI exposes this directly. The --delimiter / flag tells S3 to collapse everything after the first slash into a “common prefix.”

aws s3api list-objects-v2 \
  --bucket my-app-data \
  --prefix invoices/2026/ \
  --delimiter /

Output:

{
    "CommonPrefixes": [
        { "Prefix": "invoices/2026/05/" },
        { "Prefix": "invoices/2026/06/" }
    ]
}

Notice you got back prefixes, not folders. The friendlier aws s3 ls command does the same grouping for you and prints PRE lines for prefixes.

Creating a “folder” (and why you usually shouldn’t)

Because folders are not real, you rarely need to create one. Uploading an object with a key like reports/q2.csv instantly makes reports/ appear as a folder. You do not create the folder first.

The Console does let you make an empty folder. When you do, it secretly uploads a zero-byte object whose key ends in / (for example reports/). This placeholder is only there so the empty folder shows up in the UI.

Console steps to create an empty folder:

  1. Open the S3 console and click your bucket name.
  2. Click Create folder.
  3. Type a name (for example reports) and click Create folder.

CLI equivalent (the zero-byte placeholder object):

aws s3api put-object --bucket my-app-data --key reports/

Avoid these zero-byte placeholders in automated pipelines. They can confuse code that lists objects, and lifecycle or sync tools may treat the reports/ object as real data. Just upload objects with the full key you want.

When to design key names deliberately

Key naming is one of the few S3 decisions that is hard to change later, so think about it up front. Two things make prefixes matter beyond aesthetics:

  • Listing and filtering operate on prefixes. ListObjectsV2, aws s3 sync, and many tools filter by prefix. A clean, predictable prefix scheme (like tenant-id/year/month/) makes targeted listing cheap and fast.
  • Lifecycle and replication rules target prefixes. A rule that transitions logs/ to Glacier after 30 days only matches keys beginning with logs/. If your logs are scattered under inconsistent prefixes, the rule silently misses them.

Do I still need to randomize prefixes for performance?

No longer. Older guidance told you to add random hash prefixes to spread load. As of 2018, S3 automatically scales request throughput per prefix — at least 3,500 PUT/COPY/POST/DELETE and 5,500 GET/HEAD requests per second per prefix. You can still raise total throughput by spreading objects across multiple prefixes, but you should choose prefixes for organization and rule targeting, not for hashing tricks.

Key naming compared

ApproachExample keyWhen to useWatch out for
Date-partitionedlogs/2026/06/15/app.logTime-series data, logs, lifecycle expiry by dateListing “all of June” needs the 2026/06/ prefix
Tenant-partitionedacme-corp/uploads/file.pngMulti-tenant apps, per-tenant lifecycle or accessPer-tenant policies must match the exact prefix
Flat / opaque IDsa1b2c3d4-uuid.binContent-addressed blobs, no human browsingNo meaningful prefix grouping for rules
Mimicking a deep treeapp/users/123/photos/2026/jun/x.jpgRarely idealDeep nesting adds no benefit and clutters listings

Best practices

  • Treat keys as the single source of truth — there are no folders, only key strings and the prefixes derived from them.
  • Choose a prefix scheme that matches how you will list, expire, and replicate data, not how a desktop file manager looks.
  • Use a consistent delimiter (/) so prefix grouping and lifecycle rules behave predictably.
  • Avoid creating zero-byte folder placeholder objects in code; upload objects with their full key instead.
  • Do not add random hash prefixes for performance — S3 scales per prefix automatically. Spread across prefixes only if you genuinely exceed per-prefix request limits.
  • Keep keys under 1,024 bytes and prefer URL-safe characters to avoid encoding surprises in URLs and tools.
Last updated June 15, 2026
Was this helpful?