Skip to main content
PProfileMatch

AWS S3 Fundamentals: Storage Classes, Permissions and Static Hosting

Cloud ComputingLesson 3 of 45 min read

What you'll learn

  • Explain buckets, keys and why S3 folders are just prefixes
  • Choose a storage class from an access pattern and write a lifecycle rule
  • Describe how IAM, bucket policies and Block Public Access combine
  • Host a static site and know why CloudFront in front of a private bucket is safer

On this page

  1. Buckets, keys and objects
  2. Storage classes: paying for access patterns
  3. Lifecycle rules do the moving for you
  4. Who can read your files
  5. Static website hosting
  6. Common mistakes
  7. How this shows up in projects and interviews

Run aws s3 ls s3://my-bucket/ on a bucket full of files in tidy-looking folders, and then look for the folders in the API: they are not there. S3 stores objects, each addressed by a key such as masters/2025/ep001.wav, and the slashes are just characters in that name. The console and CLI pretend that prefixes are folders for convenience. That one fact explains most of how S3 permissions, lifecycle rules and listings behave. This lesson follows a podcast's audio archive from first upload to cost-aware storage to a public website.

Buckets, keys and objects

A bucket is a named container in one region, and its name must be unique across all AWS accounts. An object is a blob up to a very large size plus metadata, stored under a key. There is no rename: renaming copies the object to a new key and deletes the old one. S3 gives strong read-after-write consistency, so after a successful upload or overwrite, a read returns the new data.

Everyday S3 commands (placeholders, not run here)
# Bucket names are global: this one is a placeholder, choose your own.
aws s3 mb s3://example-podcast-archive-4821 --region eu-west-1

aws s3 cp ./ep001.wav s3://example-podcast-archive-4821/masters/2025/ep001.wav
aws s3 ls s3://example-podcast-archive-4821/masters/
aws s3 sync ./site s3://example-podcast-archive-4821/site --delete

aws s3api put-bucket-lifecycle-configuration \
  --bucket example-podcast-archive-4821 \
  --lifecycle-configuration file://lifecycle.json

# A temporary link to a private object, valid for one hour
aws s3 presign s3://example-podcast-archive-4821/masters/2025/ep001.wav --expires-in 3600

aws s3 ... are the high-level helper commands; aws s3api ... maps one-to-one to the underlying API and is where configuration such as lifecycle rules lives.

Storage classes: paying for access patterns

All classes store data durably across multiple facilities. They differ in how much you pay to keep the data, how much to read it, and how fast you can get it back. Specific prices change and vary by region, so the table compares behaviour only.

ClassGood forTrade-off
S3 StandardFrequently read data, such as the episodes being downloaded nowHighest storage cost per GB, no retrieval fee
S3 Intelligent-TieringData whose access pattern is unknown or changingSmall monitoring fee; moves objects between tiers automatically
S3 Standard-IA / One Zone-IAInfrequently read data you still need immediatelyLower storage cost, retrieval fee and a minimum storage period; One Zone keeps data in a single zone
S3 Glacier Instant RetrievalArchives read rarely but needed in millisecondsCheap storage, higher retrieval cost
S3 Glacier Flexible RetrievalBackups you can wait minutes or hours forObjects must be restored before you can read them
S3 Glacier Deep ArchiveLong-term compliance copiesCheapest storage; retrieval takes the longest

Reading an archived object before restoring it fails with an InvalidObjectState error saying the operation is not valid for the object's storage class. That is the signature of a Flexible Retrieval or Deep Archive object, and the fix is to start a restore and wait.

Lifecycle rules do the moving for you

Instead of moving files by hand, declare what should happen as objects age. This rule watches the masters/ prefix, moves objects to Standard-IA after 30 days and to Glacier after 90, and deletes them after two years. It is applied with the put-bucket-lifecycle-configuration command shown in the previous block.

lifecycle.json
{
  "Rules": [
    {
      "ID": "age-out-episode-masters",
      "Status": "Enabled",
      "Filter": { "Prefix": "masters/" },
      "Transitions": [
        { "Days": 30, "StorageClass": "STANDARD_IA" },
        { "Days": 90, "StorageClass": "GLACIER" }
      ],
      "Expiration": { "Days": 730 }
    }
  ]
}

Who can read your files

Access is the intersection of several layers. An identity's IAM policy can allow S3 actions. A bucket policy is a resource-based policy attached to the bucket, useful for granting access across accounts or to a service. Block Public Access is a master switch that overrides policies and is on by default for new buckets, and Object Ownership settings now disable ACLs by default so policies stay the single source of truth. For a private object that one person needs for an hour, create a presigned URL, a time-limited link that carries the signer's permissions, as shown in the command block.

Static website hosting

A static site is plain HTML, CSS, JavaScript and images, with no server code, which S3 can serve. There are two ways to do it.

  • S3 website endpoint. Simple to learn: upload the files, enable website hosting and set the index and error documents. The endpoint serves plain HTTP only, and the objects must be publicly readable, so you must deliberately relax Block Public Access.
  • CloudFront in front of a private bucket. The better pattern for real sites. CloudFront, the content delivery network, gets HTTPS and caching, and an origin access control lets only CloudFront read the private bucket, so nothing in the bucket is public.
The simple route: upload and enable hosting (placeholders)
aws s3 sync ./site s3://example-podcast-site-4821 --delete

aws s3 website s3://example-podcast-site-4821 \
  --index-document index.html \
  --error-document error.html

The website command only turns on the feature and names the documents; making the content readable is a separate policy decision, which is exactly why the CloudFront route is safer. If you later need caching theory, the system design caching lesson explains why a CDN in front of storage helps.

Common mistakes

  • Making a whole bucket public to fix one access error. Symptom: it works, then a private file turns up in search results or access logs show strangers. Keep Block Public Access on and use presigned URLs or CloudFront.
  • Bucket name already taken. Symptom: BucketAlreadyExists from aws s3 mb. Names are global; add a random suffix.
  • Wrong region in the command. Symptom: an error saying the bucket must be addressed using the specified endpoint, or a redirect error. Pass --region or configure the correct default.
  • Deleting a non-empty bucket. Symptom: BucketNotEmpty. Empty it first, including old object versions if versioning is on, which is also why versioned buckets quietly grow.
  • Using `sync --delete` with a wrong source path. Symptom: the destination is emptied to match an empty folder. Run it with --dryrun first.

How this shows up in projects and interviews

S3 appears in nearly every AWS architecture, so interviews ask how you would store user uploads, serve a static site, or reduce the storage bill for logs that are rarely read. The expected answers are presigned URLs or a private bucket behind CloudFront, and lifecycle rules with an appropriate storage class. Be ready to say why S3 is not a file system, that is, no in-place edits and no real folders, and how you would keep a bucket private by default. Many security incident reports mention a misconfigured public bucket, so showing you default to private signals good habits.

Try it yourself

Design the S3 setup for a podcast: the current episode must be fast and cheap to download worldwide, masters older than 90 days should be rarely touched, and nothing may be public except through the site. List the buckets or prefixes, which storage class each uses, the lifecycle rule and how listeners reach the audio.

Show a hint

Think of one private bucket with prefixes, a lifecycle rule on the masters prefix, and CloudFront in front for listener downloads.

Key takeaways

  • S3 stores objects under keys; folders are a display convenience built on prefixes.
  • Storage classes trade storage price against retrieval cost and speed; lifecycle rules move data automatically.
  • Keep Block Public Access on and share private files with presigned URLs or CloudFront.
  • The S3 website endpoint is HTTP-only and needs public objects; CloudFront with a private bucket is the better pattern.

Test yourself

A trick from this lesson's ride: There are no folders in S3, only long names with slashes in them. Four more tricks like it wait along the route, each followed by a question.

Ride this lesson

Frequently asked questions

What are the S3 storage classes and when should I use each?

Standard suits frequently accessed data, Intelligent-Tiering handles unknown or changing access, and Standard-IA and One Zone-IA suit infrequently read data that must stay available immediately. The Glacier classes are for archives and differ in retrieval speed. Pick by how often and how fast you need to read the data, and let lifecycle rules move objects between classes.

How do I make an S3 bucket private but still share a file?

Keep Block Public Access enabled and generate a presigned URL for the object, for example with aws s3 presign, which makes a time-limited link. For a website or many downloads, put CloudFront in front of the private bucket with an origin access control so only the CDN can read the objects.

Can I host a static website on S3?

Yes. Upload the files, enable static website hosting and set an index document. The S3 website endpoint only supports HTTP and needs publicly readable objects, so for production most people use CloudFront with a private bucket to get HTTPS, caching and tighter access control.