GZIP compression
Amazon S3
static files
cloud storage
website optimization

GZIP Compression on static Amazon S3 files

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Amazon S3 does not gzip your static files on the fly the way an application server might. If you want gzip-compressed static assets from S3, the usual pattern is to compress the files yourself before upload and set the correct metadata so browsers know the object is encoded with gzip.

Know What S3 Does and Does Not Do

S3 is object storage. It serves the object bytes you upload along with the metadata you attach. That means:

  • S3 will not dynamically compress your file for a request
  • S3 will happily serve a precompressed file if you upload it that way
  • the Content-Encoding header tells the client how to decode it

This distinction is important because people often assume S3 behaves like NGINX or Apache with automatic gzip enabled. It does not.

Compress the File Before Upload

For text-based assets such as JavaScript, CSS, JSON, SVG, and HTML, precompression is common.

bash
gzip -k app.js

This creates app.js.gz while keeping the original file. When uploading the compressed object to S3, set both the content type and content encoding metadata.

bash
aws s3 cp app.js.gz s3://my-bucket/assets/app.js \
  --content-type 'application/javascript' \
  --content-encoding 'gzip'

Notice that the object key remains app.js even though the uploaded bytes came from app.js.gz. That is often the cleanest approach for static site hosting because the URL stays normal while the payload is compressed.

Set Metadata Correctly

The two most important headers are:

  • 'Content-Type, which describes the original media type'
  • 'Content-Encoding, which tells the client the payload is gzip-compressed'

If you omit Content-Encoding: gzip, browsers may try to treat the compressed bytes as plain text and the file will appear broken.

For example, a CSS upload should look like this:

bash
aws s3 cp styles.css.gz s3://my-bucket/assets/styles.css \
  --content-type 'text/css' \
  --content-encoding 'gzip'

That metadata is the difference between a working compressed asset and unreadable output.

Use CloudFront Intentionally

Many S3-backed sites sit behind CloudFront. In that setup, you have two broad options:

  • upload precompressed objects and serve them with the right metadata
  • let CloudFront apply compression for eligible responses when configured to do so

Precompressed assets give you explicit control. CloudFront compression can be simpler operationally for some setups, but you still need to understand what is happening at each layer.

The important thing is not to mix assumptions. If you uploaded plain files to S3 and expected S3 itself to gzip them, nothing will happen.

Compress Only the Right File Types

Gzip helps mostly for text-based files. It usually does not help for already compressed binary assets such as:

  • JPEG
  • PNG
  • MP4
  • ZIP
  • PDF in many cases

Trying to gzip those often wastes CPU and may even increase size slightly. Focus compression on text payloads that benefit from repeated patterns.

Verify the Result After Upload

Do not assume the metadata is correct. Check the object headers.

bash
aws s3api head-object \
  --bucket my-bucket \
  --key assets/app.js

You should see something like:

  • 'ContentType set to the correct MIME type'
  • 'ContentEncoding set to gzip'

That verification step catches most configuration mistakes immediately.

Common Pitfalls

  • Expecting S3 to compress static files automatically leads to confusion because S3 serves stored objects, not dynamic encodings.
  • Uploading a .gz file without setting Content-Encoding: gzip makes browsers treat compressed bytes as if they were plain text.
  • Setting the object key to app.js.gz when the site expects app.js can break asset URLs unless your frontend is explicitly built for that naming scheme.
  • Compressing already compressed binary files wastes effort and usually provides little or no benefit.
  • Forgetting to verify metadata with head-object leaves you debugging browser behavior when the real issue is incorrect S3 headers.

Summary

  • S3 does not apply gzip dynamically; you must upload precompressed files if you want gzip from S3 itself.
  • Set both Content-Type and Content-Encoding correctly when uploading compressed assets.
  • Use compression primarily for text-based static assets such as JS, CSS, HTML, JSON, and SVG.
  • Verify the stored metadata after upload instead of assuming the CLI flags did what you intended.
  • If CloudFront is involved, decide clearly whether compression happens at the CDN or via precompressed S3 objects.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.