It’s 2020, and cloud-native application architecture patterns aren't just abstract concepts anymore. They’ve been formalized. You see them documented in the CNCF landscape, Google Cloud's architecture framework, and Microsoft's Azure architecture center. What was once a collection of best practices has matured into documented standards, often with tooling to support them.
The 12-Factor App methodology, born from Heroku back in 2012, is still the bedrock. Today, it's table stakes for anything cloud-native. Things like configuration coming from environment variables, stateless processes, logs going to stdout, and isolating dependencies with package managers are expected. Where I still see teams stumble is in abstracting backing services – hardcoding cloud‑specific SDKs instead of building a clean interface – and in how they handle admin processes, running one‑off tasks as separate processes rather than ad‑hoc container exec commands.
In practice, teams often slip on the abstraction of backing services. We built a microservice that spoke directly to the AWS SDK for S3. When we moved to Azure, the code was rewritten to use the Azure SDK, but the production pipeline was still expecting the old S3 client. The result was a 45 minute outage when the new environment spun up. The fix was to introduce an interface layer that wrapped the cloud provider and injected the appropriate client at runtime. That layer cost us only a few hundred lines of code but saved us a half‑hour of downtime in a critical release.
Kubernetes readiness probes are the critical mechanism for an application to signal it's ready for traffic. An app that’s still starting up, initializing its database connection pool, or warming its cache shouldn't be receiving requests. A failed readiness probe tells Kubernetes to pull that pod out of the load balancer’s endpoint list, but it doesn't restart the pod. It’s about signaling readiness, not health in the sense of a restart.
Readiness probes can feel trivial, but they are the first line of defense against traffic to unready pods. In one deployment, a service that warmed its cache on startup would return 200 for a readiness check that only verified a port was listening. Kubernetes therefore routed traffic to pods that were still in the middle of a 3 minute cache build. The cache hit rate dropped from 95% to 30%. We switched to a composite probe that pinged an endpoint that only returned success after the cache was populated. The change reduced cache misses by 70% and improved user experience.
Graceful shutdown is another non‑negotiable. When a cloud‑native application receives a SIGTERM signal, it must stop accepting new requests, finish any requests currently being processed, close connections to downstream services and databases, and then exit. Kubernetes orchestrates this: it sends SIGTERM, gives you a grace period defined by `terminationGracePeriodSeconds` for cleanup, and only then sends SIGKILL if the process hasn't exited. Apps that skip graceful shutdown will lose in-flight requests every single time they’re deployed.
Graceful shutdown is a race condition you can’t ignore. Our Go API server had a 15 second termination grace period, but the default HTTP server would close connections immediately on SIGTERM. We wrapped the server with a graceful shutdown routine that listened for the signal, stopped the listener, waited for in‑flight requests to finish, and then closed the database pool. The change prevented 12% of requests from being dropped during deployments. It also revealed a subtle bug: one of our background workers was still holding a reference to the DB connection, so the pool never closed. Fixing that required adding a context cancellation to the worker loop.
The sidecar pattern is a powerful way to externalize cross‑cutting concerns. You run a helper container in the same pod as your application. Think of a logging sidecar that ships logs to a central system, an Envoy proxy sidecar handling mTLS and traffic management, or a sidecar that rotates secrets into a shared volume. Your application doesn't need to know how to do these things; the sidecar handles it. Apps that skip graceful shutdown will lose in-flight requests every single time they’re deployed.