Cloud Native Application Design

"Cloud native" is a label often misapplied to mean "runs in a cloud." The useful definition: an application designed to take advantage of cloud-platform properties — elasticity, managed services, ephemerality, distributed-by-default — rather than fighting them.

This page is about what cloud-native actually requires and the patterns that make applications work well in cloud environments.

The 12-factor principles

Heroku's 12-factor app is the canonical statement. The principles that have aged well:

  1. Codebase: one codebase per service; many deploys.
  2. Dependencies: explicit; no system-wide assumptions.
  3. Config: environment variables, not in code.
  4. Backing services: databases, queues are attached resources; swappable.
  5. Build/release/run: strict separation of build artifacts and deployment config.
  6. Processes: stateless; share-nothing.
  7. Port binding: app exposes HTTP via port; doesn't depend on a specific server.
  8. Concurrency: scale via process model.
  9. Disposability: fast startup, graceful shutdown.
  10. Dev/prod parity: minimize environment differences.
  11. Logs: write to stdout/stderr; aggregator handles routing.
  12. Admin processes: one-off tasks run in the same environment as the app.

Many of these are obvious now. They weren't in 2011 when the manifesto was written. The cloud-native baseline is roughly "12-factor plus container."

What cloud-native gives you

When the application follows these patterns:

What cloud-native costs

The principles aren't free:

Some applications fight these constraints. Some workloads — long-running stateful services, batch jobs with local-disk needs, applications with hard-coded paths — don't fit.

Patterns that work in cloud-native

Stateless services

Application instances hold no state. State lives in databases, caches, queues. Any instance handles any request. Scaling means adding instances.

Managed backing services

Use the cloud's managed databases, queues, caches rather than self-hosting. The cost is real but operational simplicity is large.

Externalized configuration

Environment variables, config services (AWS Parameter Store, GCP Secret Manager), or sidecars for config delivery.

Health checks

/health endpoints (or similar) that the orchestrator polls. Unhealthy instances get replaced automatically.

Graceful shutdown

Receive SIGTERM, stop accepting new work, drain in-flight requests, exit. Containers and serverless platforms expect this.

Circuit breakers and retries

Distributed systems fail in distributed ways. Resilience patterns — circuit breakers, exponential backoff, bulkheads — are not optional at scale.

Observability

Structured logs, metrics on all the things, distributed traces. The ecosystem (OpenTelemetry, Prometheus, Grafana, Datadog) is standardized.

Lift-and-shift vs. re-architect

Two migration paths:

Lift-and-shift

Run the existing application in the cloud with minimal changes. Pros: fast, cheap, low risk. Cons: doesn't capture cloud benefits; often costs more than on-prem because cloud pricing assumes scaling.

Re-architect

Redesign for cloud-native. Pros: captures the benefits. Cons: long, expensive, risky.

Most successful migrations do both: lift-and-shift first to escape the data center, then re-architect incrementally. Pure rewrites usually fail.

Common patterns to avoid

Common failure patterns

Further Reading