Why There Are No Folders
In one line
Object storage has no directories. img/2026/logo.png is just one long key that contains slashes, and that fact is the basis of its scalability.
Why it was needed
A filesystem is a tree. Every directory has an inode, and to open a single file you walk down the path checking the permissions and existence at each step. This structure is excellent on a local disk. But when you try to hold 10 billion files across 100 nodes, it becomes a problem. The upper nodes of the tree become contention points for all access, and if you put a million files in one directory, ls takes minutes.
Object storage throws away the tree. There is only a flat key-value space. A key is just a string, and the slash has no special meaning. What aws s3 ls or the console shows you as folders is only a view grouped by prefix.
What this simplification buys is that you can hash a key to decide which node to put it on. No central directory server is needed, and adding nodes increases capacity and throughput together.
How it works
What you give up in exchange is also clear.
First, there is no partial modification. An object is written whole or read whole. To change 1 byte in the middle of a 1GB file, you must upload 1GB again. So it does not suit data that keeps being appended to, like log files.
Second, there is no rename. A rename is a copy followed by a delete. To change the prefix img/ to images/, you must copy and delete every object under it. This is why prefix design has to be done well at the start.
Third, there are no POSIX semantics. There are no file locks, hard links or atomic renames. This is why you should not put database files in object storage.
Fourth, listing is expensive. Prefix-based listing is possible, but to find "those of 1MB or more" or "those modified yesterday," you must scan everything. If you need metadata search, you set up a separate index.
What it looks like in the field
A common mistake in prefix design is putting the date at the very front. With 2026-08-20/user/..., all the writes arriving that day pile into the same prefix range. In implementations that partition by key order, this becomes a hotspot. It is safer to put a value that scatters (such as the first two characters of a hash of the user ID) at the front.
It is also good to remember the workloads that truly suit object storage — large, immutable data that is written once and read many times. Images, videos, backups, training datasets and build artifacts. Conversely, small data that is frequently partially modified belongs in a database.
What happens when you use it like a filesystem
S3 has no directories, and a key is just a long string. / is a convention used to make the screen look like a tree. This difference shows up in three ways in practice.
There is no rename. mv is copy + delete. If you rename a 100GB directory, you copy 100GB and delete it. That is why you have to get key design right at the start.
There are no empty directories. When you delete all the objects inside, that "folder" disappears. Creating s3://bucket/logs/ is just creating a 0-byte object.
Listing is expensive. LIST returns in pages of 1,000. With a million objects, that is 1,000 round trips. If you think of a filesystem's ls and call the list on every request, cost and latency rise together.
How to design keys
In the past it was said that "you must scatter the front part randomly to get performance," but now S3 partitions automatically by prefix, so it is better to keep a readable order.
logs/2026/09/06/api/instance-42.jsonl.gz
│ └ 시간 계층 — 수명주기 규칙과 부분 조회에 유리
└ 종류
❌ 2026-09-06-api-instance-42.jsonl.gz ← 접두로 못 자른다
If you lay out time as a hierarchy, it is easy to write a rule that deletes only logs/2026/09/ or moves only that month to a cheaper tier. Conversely, if you join it into one string, you cannot build a prefix condition.
When a filesystem is right
Object storage is not always the answer.
| Object storage | Filesystem (NFS, EFS) | |
|---|---|---|
| Partial modification | Not possible (full re-upload) | Possible |
| Rename | Copy + delete | Instant |
| Locking | None | Yes |
| POSIX semantics | None | Yes |
| Scalability | Practically unlimited | Has limits |
| Unit price | Cheap | Several times more expensive |
If an existing application partially modifies files or uses locks, you cannot simply move it to object storage. You can mount it with a tool such as s3fs, but partial modification becomes a full re-upload and locking is only imitation, so both performance and consistency get worse.
What you write and then don't change (logs, images, backups, model weights) suits object storage, and what you keep editing (working directories, DB files) does not.
What we do in the next lab
You attach an alias to a local S3-compatible server, create a bucket, upload objects and organize them by prefix. You check what an ETag is by comparing it with a local md5, and also cover server-side copy and specifying the Content-Type.