How do you handle a deployment that passes Dev and UAT but fails in Production, and what systematic approach prevents environment-specific failures?
Quick Answer
Production-only failures are caused by environment differences: tighter resource quotas, stricter network policies, different secrets or certificates, higher traffic load, or missing IAM permissions. Prevention requires environment parity through identical Helm charts with per-env values, pre-production load testing, and promotion gates that verify production-specific dependencies.
Detailed Answer
Think of a car that runs perfectly on a test track but breaks down on a real highway. The test track has smooth roads, no traffic, and perfect weather. The highway has potholes, rush hour, and rain. The car itself did not change — the environment did. Production failures after Dev/UAT success follow the same pattern: the application code is identical, but the surrounding infrastructure, load, and security boundaries are different.
The most common causes of production-only failures are resource constraints (production has stricter quotas or different instance types), network restrictions (production network policies block connections that were open in UAT), secret and certificate differences (production uses different database endpoints, API keys, or TLS certificates), external dependency behavior (third-party APIs rate-limit production traffic differently), and traffic volume (production handles 100x the requests that UAT sees, exposing concurrency bugs or connection pool exhaustion).
To diagnose a production-only failure, compare the environment configurations side by side. Use kubectl diff to compare manifests between UAT and production. Check resource quotas, network policies, service mesh rules, and ingress configurations. Examine the application logs for connection errors to databases, caches, or external APIs. Use kubectl top to compare actual resource usage between environments. Check whether the production node pool has different instance types, kernel parameters, or container runtime versions.
Prevention requires several practices. Use the same Helm chart or Kustomize base across all environments, varying only through values files. Implement a staging environment that mirrors production networking, security, and scale. Run automated smoke tests and integration tests after every deployment to every environment. Use canary deployments in production so that only a small percentage of traffic hits the new version initially. Maintain a deployment checklist that verifies production-specific prerequisites: database migrations completed, feature flags configured, secrets rotated, and external dependencies reachable.
The non-obvious gotcha is that even with perfect environment parity, production can still fail due to data differences. A database migration that works on a small Dev dataset can lock tables for minutes on a production dataset with millions of rows. Connection pools that are adequate for UAT traffic can be exhausted under production load. Architects should include data volume and traffic simulation in pre-production testing, not just functional correctness.