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.
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-Encodingheader 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.
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.
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:
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.
You should see something like:
- '
ContentTypeset to the correct MIME type' - '
ContentEncodingset togzip'
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
.gzfile without settingContent-Encoding: gzipmakes browsers treat compressed bytes as if they were plain text. - Setting the object key to
app.js.gzwhen the site expectsapp.jscan 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-objectleaves 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-TypeandContent-Encodingcorrectly 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
- Having trouble creating a basic AWS AMI with Packer.io. SSH Timeout
- head command for aws s3 to view file contents
- Health Checks in GKE in GCloud resets after I change it from HTTP to TCP
- Helm charts and Ingress resources
- Hadoop Is it possible to avoid replication for certain files?
- Hamming numbers for ON speed and O1 memory
- Heroku deploying Deep Learning model
- Heroku tensorflow 2.2.1 too large for deployment

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack 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.