Amazon S3 access & file storage
How S3 buckets store application files, how access is granted, and how to share files without making a bucket public.
- Difficulty
- Intermediate
Amazon S3 stores files — uploads, documents, images, exports, backups. Applications use it because it's durable and effectively unlimited. The recurring risk is simple: a misconfigured bucket makes private files public, and once an object is public, anyone who finds or guesses its address can read it.
Quick summary
Keep Block Public Access switched on at both account and bucket level. Grant applications access through an IAM role scoped to a single bucket. When a user needs to download a private file, generate a presigned URL that expires — never make the object public to solve a sharing problem.
How S3 is organised
- Bucket — a named container. Bucket names sit in a shared namespace, so a name has to be unique across every AWS account in the same group of Regions (AWS calls that group a partition).
- Object — one stored file, identified by a key that usually looks like a path (
uploads/2026/report.pdf). - Region — where the data physically lives, which matters for latency and for data-residency obligations.
Controlling access
Several mechanisms overlap, which is why misconfiguration is common:
| Mechanism | What it does |
|---|---|
| Block Public Access | Master switch, set on a bucket, an account or a whole AWS Organization; it overrides bucket policies and ACLs, and the most restrictive setting wins |
| Bucket policy | JSON rules attached to the bucket saying who may do what |
| IAM policy | Permissions attached to a user or role |
| Presigned URL | A temporary, expiring link to one object |
| ACLs | Legacy per-object permissions; disabled by default on new buckets and best left that way |
Block Public Access should stay on
Leave it enabled unless you are deliberately hosting genuinely public assets, and even then prefer a CDN in front of a private bucket. Turning it off "just to test something" is how private documents end up publicly readable.
Giving an application access
Create an IAM role for the application rather than an IAM user with long-lived keys.
Scope the policy to one bucket, and to the specific actions needed —
typically s3:GetObject and s3:PutObject, not s3:*.
Restrict by prefix where it helps. A service that only handles user uploads doesn't need read access to your backups sitting in the same bucket.
Never grant s3:DeleteBucket to an application. Nothing routine
requires it.
Sharing a private file
The correct answer is almost always a presigned URL: a link, generated on demand, that grants time-limited access to one object and then expires. Set the shortest expiry that's practical: a link generated from the S3 console can last at most 12 hours, and one generated with the AWS CLI at most seven days. The link carries the permissions of whoever or whatever created it, so generate it from the application, not from a personal login.
This is how a well-built application lets someone download their own invoice or export without any of the files being public.
Protecting against deletion
Storage durability is not the same as protection from mistakes. A deleted object is gone unless you planned ahead.
Common questions
Is data in S3 encrypted?
Yes. Every bucket has encryption configured by default, using keys S3 manages for you, and new objects are encrypted at rest automatically. For sensitive data you can supply your own key through AWS KMS, which adds auditable control over who can decrypt — useful for compliance obligations.
Why is our S3 bill higher than expected?
Usually one of: old object versions accumulating because versioning is on without lifecycle rules, incomplete multipart uploads left behind, or data transfer out (egress) rather than storage itself. Serving files through a CDN instead of straight from S3 often reduces the transfer cost; check AWS's current S3 and CloudFront pricing before assuming either way.
Can we use S3 for website backups?
Yes, and it's a good destination — most backup tools support it directly. Use a dedicated bucket with versioning on and an IAM user restricted to that bucket alone. That's the deliberate exception to the "role, not user" advice above: AWS names tools that can't assume a role, such as WordPress plugins, as a case where a long-lived access key is the right answer. See backup plugins explained.
Does it matter which region we pick?
Yes, for two reasons. Latency — pick a region near your users. And law — if you handle personal data subject to residency requirements, the region determines which jurisdiction the data sits in. See data privacy basics.
Related guides
Need a hand?
Learn more
Last updated
AWS KMS & encryption keys
What AWS Key Management Service does, how key policies control access, why rotation matters, and why deleting a key is irreversible.
ClamAV & scanning uploaded files
What ClamAV does, why applications that accept file uploads need malware scanning, and how it fits into a wider upload-security approach.