From 642 Megabytes to Nine

Published May 15, 2026Updated May 14, 20263 min read

By Junaid Ahmed


Our admin app is a 9-megabyte React build.

Every time I deployed it to Google Cloud Build, the upload took several minutes and pushed 642 megabytes of context across the wire. Sixty times the size of the actual artifact.

I had been ignoring this for weeks because the deploys worked. Slow, but they worked.

I shouldn't have been ignoring it.


What was in the upload

The Cloud Build pattern: run a build locally, generate a dist-admin/ folder, tell gcloud builds submit to upload the working directory, and Cloud Build builds a Docker image from your Dockerfile.

The Dockerfile for our admin app does three things. Copies dist-admin/ into nginx. Copies one nginx config template. Copies one entrypoint script. That's the entire image.

The upload was including everything else in the project. Every other app's source. Every other app's node_modules. The documentation folder. Marketing imagery from the public website. The community app's Next.js install, 470 megabytes alone, because Next.js has opinions about dependencies.

The Dockerfile didn't use any of it. The upload was carrying it anyway.


Blacklist vs. whitelist

The reason was a five-line config file called .gcloudignore. Written as a blacklist: ignore node_modules, ignore .git, ignore some build folders. Anything not on the list got uploaded.

The problem with blacklists is the list grows as the project does, and the gaps don't shout at you. When we added a new app to the monorepo, the .gcloudignore didn't change. When the marketing folder grew with cover images, the .gcloudignore didn't change. The Docker container didn't get bigger, because the Dockerfile didn't reach for those files, but the upload kept growing in the background.

I rewrote .gcloudignore as a whitelist. Five lines:

*

!Dockerfile

!nginx.conf.template

!docker-entrypoint.sh

!dist-admin

!dist-admin/**

Ignore everything by default. Then list the things you actually want included.

The upload dropped to about nine megabytes.


The thing this is really about

This is a boring infrastructure post. The interesting part is what made me finally look at it.

I had been blaming "Cloud Build is slow." I had been working around it, kicking off a deploy and switching tabs. Batching changes so I deployed less often. Choosing not to ship small fixes because the friction wasn't worth it for a one-line change.

The friction was real. The cause was a config file from twelve months ago.

This is a pattern I see in my own work over and over. My first hundred podcast videos were recorded in front of a beige wall with a ring light that made me look like I was being deposed. I kept thinking the content would carry it. The room was doing all the talking before I opened my mouth, and I kept not looking at the room. Eventually I turned the camera on and watched what everyone else had been watching, and I fixed it in an afternoon.

I tolerate a thing that bugs me. I optimize around it. Eventually I look at it directly and fix it in ten minutes. Always the same pattern.


What it costs you

The cost wasn't the slow deploys. The cost was every small fix I didn't ship because it wasn't worth the wait.

PodGlue is meant to make the small follow-up easy. The email to the guest. The asset they need. The thank-you note. The whole product is built on the belief that the small things compound when you don't let friction kill them.

I keep that belief in my product and then I let friction kill the small things in my own work. The deploy pipeline was making me a worse builder. The whole time, the fix was sitting in a five-line file I'd written and never looked at again.


The next time something in your workflow makes you sigh, ask whether you've actually looked at it, or whether you've just been routing around it for so long that the routing has become invisible.

The cost of the routing is the build you didn't ship.

Junaid Ahmed is the host of Hacks & Hobbies and the founder of PodGlue.

Ready to make every episode compound?

PodGlue is the operating system for relationship-driven podcasters.

Get Started Free

Related reading