./ahmedhashim

Why I Develop on Production Hardware

I once spent a day debugging why a python import wasn’t working in production. The code ran without issues on Ubuntu during development but crashed
consistently when deployed to Alpine Linux servers.

The culprit? I was developing on a glibc system but deploying with musl-based Docker images.

This isn’t an edge case. When you install a python package on Ubuntu, you’re getting wheels compiled against glibc. Those same wheels will mysteriously fail on Alpine Linux because musl handles dynamic linking differently.

The differences go beyond binary compatibility: DNS resolution behaves differently between glibc and musl systems. Applications that could resolve hostnames perfectly during development suddenly timeout in production because musl’s resolver has different fallback behavior.

Character encoding, memory management, and threading behavior also differ between these systems. The subtle bugs from these architectural differences can result in a few gray hairs.

The solution? Use the same OS and runtime versions from development through production. If you’re deploying to Alpine Linux, develop on Alpine Linux. If your production uses Python 3.9.2, don’t develop on 3.9.7 because it’s slightly newer.

I don’t expect developers to abandon their Mac workflows, but Docker makes testing on production images trivial. A quick docker run before deployment can save hours of production debugging.