Articles

12/15-Factor App and Cloud-Native Standards: What Your Application Should Bring to Run on Kubernetes

An application as a container, surrounded by a ring of fifteen checkpoints, three of them in teal

Almost every application ends up in a container at some point, and almost every discussion about “cloud-native” sooner or later arrives at the same question: what does an application actually need to bring so that a platform can operate it reliably? The best-known answer is the Twelve-Factor App, extended by three factors into the 12/15-factor app. This article puts the factors in context, shows how the CNCF Cloud Native Maturity Model places them in a wider frame, and sums up what matters in practice when you run on Kubernetes.

Why the twelve factors exist

The Twelve-Factor App emerged at Heroku in the early 2010s, formulated by Adam Wiggins. He and his team had run hundreds of applications on a shared platform and kept seeing the same patterns: applications that could not be deployed automatically because configuration lived in the code. Applications that would not scale horizontally because they held local state. Applications that behaved differently in production than on a developer machine.

The twelve factors are the answer to that. They describe neither a technology nor a stack, but a division of responsibility between application and runtime environment. They define what a platform may expect from an application, and what the application may expect from the platform in return. If the application meets those expectations, the platform can start it, stop it, multiply it and move it without knowing anything about the application itself. Everything that runs on container orchestration today rests on precisely this.

The twelve factors at a glance

In their original order as published at 12factor.net, each with the core of the principle:

  1. Codebase: One codebase per application, tracked in version control, from which any number of deployments are produced.
  2. Dependencies: Dependencies are declared explicitly and isolated. Nothing is assumed to exist in the system environment.
  3. Config: Everything that differs between environments lives in the environment, not in the code.
  4. Backing Services: Databases, queues and caches are attached resources, swappable through configuration.
  5. Build, Release, Run: The three stages are strictly separated. A release is immutable and uniquely identifiable.
  6. Processes: The application runs as one or more stateless processes. State belongs in a backing service.
  7. Port Binding: The application exports its service itself via a port rather than assuming an external web server.
  8. Concurrency: Scaling happens horizontally through additional processes, not through larger machines.
  9. Disposability: Processes start quickly and shut down cleanly. They can be replaced at any moment.
  10. Dev/Prod Parity: Development, staging and production stay as similar as possible.
  11. Logs: Logs are an event stream written to stdout. The application writes no log files and rotates nothing.
  12. Admin Processes: One-off tasks such as migrations run as a separate process against the same release.

This list is roughly fifteen years old and still valid in large part. Anyone building a container image today and deploying it to Kubernetes implements most of these points implicitly, whether deliberately or not.

What has changed since then

The Twelve-Factor App describes a single application on a PaaS. That was the reference case at the time. Since then, operations have shifted in three directions.

First, the single application became a distributed system. Where a monolith once ran against one database, dozens of services now communicate over the network. The interface between them has become the critical artefact, and the original model says nothing about it.

Second, operations themselves have become declarative. Kubernetes expects health probes, resource requests, graceful shutdown and defined termination periods. These are concrete technical requirements that go beyond the original “start fast, exit cleanly”.

Third, security has moved from a peripheral concern to a basic precondition. In a distributed system there is no trusted internal network in which service-to-service calls may pass unchecked.

The three additional factors

Kevin Hoffman closed these gaps in 2016 in Beyond the Twelve-Factor App. He reorders the existing factors, sharpens individual formulations, and adds three points. When we talk about the 12/15-factor app, we mean the twelve factors plus these three.

13. API First

The interface is designed before implementation begins. A versioned API contract, for instance as an OpenAPI or Protobuf definition, is a service’s first artefact, not a by-product of its completion.

The practical benefit lies in decoupling: consuming teams can develop against mocks, breaking changes become visible in review rather than in production, and contract tests can be wired into the pipeline. In an architecture made of many services, this is the difference between independent teams and a distributed monolith.

14. Telemetry

The original log factor treats logs as an event stream. That is necessary but not sufficient. Hoffman widens the view to three kinds of data: application metrics such as throughput and error rates, health metrics such as status and availability, and domain events from the business logic.

At the core of this factor is a question of perspective. With a handful of servers you can log into a machine and look. With hundreds of short-lived pods you cannot. Telemetry therefore has to be part of the application rather than something layered on from the outside afterwards.

What an application does not reveal about itself, no platform can make visible after the fact.

In today’s practice this means structured logs, a Prometheus-compatible metrics endpoint, and distributed tracing with context headers passed through. OpenTelemetry has established itself as the standard for this.

15. Authentication and Authorization

Security is not a factor you retrofit. Every access, including between two internal services, is authenticated and authorised. Identities are short-lived, permissions are explicit, and secrets never live in the image or the repository.

On a Kubernetes platform this means several layers working together: RBAC for cluster access, central secrets management, mTLS for service-to-service communication, and policy enforcement that rejects insecure configurations before they take effect.

Cloud-native standards beyond the factors

The 15 factors describe the application. How platform, delivery and security evolve around that application is described by the CNCF’s Cloud Native Maturity Model. It is vendor-neutral, refers only to projects with graduated or incubating status in the CNCF, and looks at five aspects: People, Process, Policy, Technology and Business Outcomes. For each aspect it describes five levels, from Level 1 Build through Operate, Scale and Improve to Level 5 Adapt.

For the question of whether an application can be operated, the Technology aspect is the relevant one. Among other things, it covers application patterns, container and runtime management, release and operations, testing and issue detection, and security and policy. From the step into production (Level 2) at the latest, the model expects things that follow directly from the factors:

  • Pods are ephemeral. Availability comes from multiple replicas, PodDisruptionBudgets and TopologySpreadConstraints, not from a particularly stable single pod.
  • Configuration is externalised. ConfigMaps and Secrets instead of configuration baked into the image.
  • Probes are meaningful. A readiness probe checks whether the application can actually serve requests, not just whether the process is running.
  • The supply chain is traceable. Versioned images, image scanning and an SBOM per release.
  • Resources are sized. Resource requests and limits are set and match actual consumption.

The platform side of these levels can be standardised: GitOps, observability, secrets management, policy enforcement and backup & recovery look the same at almost every company. The application side cannot. It decides how much a platform can actually take off your hands.

What this means for operations

The factors and the maturity model result in a manageable set of characteristics. No application has to meet all of them from day one, and a less cloud-native application can still run on Kubernetes. But every point it meets means updates, node rotations and scaling need less manual work and run without disruption for your users.

What makes an application operable
  • One immutable artefact: versioned OCI images, the same image version in every environment, no latest or other floating tags.
  • Configuration from the environment, secrets from secrets management: no credentials in the image, the repository or the logs.
  • State in backing services: databases, object storage and caches instead of sessions in memory or files on the pod’s local filesystem.
  • A clean lifecycle: meaningful liveness and readiness probes, graceful shutdown on SIGTERM, resource requests and limits set.
  • Observability from within: logs to stdout, structured where possible and without personal data or credentials in plain text, plus application metrics.
  • Least privilege: running as non-root, without privileged containers.
When someone else takes over operating the application

Things change when an external provider, rather than your own team, is to look after the application around the clock. Then it must not only be operable but also manageable from the outside, without anyone knowing its internals. On kloudease this is SREaaS: we take over alerting and first response for your application. The 12/15-factor principles are a prerequisite for this, and further requirements include:

  • deployment via Helm charts with full rollback capability, rollback-safe APIs and database schemas following the expand/contract principle
  • stateless, HPA-capable deployments with multiple replicas and a PodDisruptionBudget
  • Prometheus-compatible metrics for alerting and error rates, plus a functional health endpoint
  • structured logs (JSON) with a correlation ID
  • an agreed set of alert rules with a runbook for each critical alert
  • an SBOM per release

The complete list is in the SREaaS document. It is checked in a conformance review before the start. If you want to know beforehand where your application stands, the Production Readiness package is the right starting point.

What makes the difference in practice

Not all points are equally hard. Most follow naturally once a team containerises consistently. Three, by contrast, we see regularly as genuine obstacles when applications migrate to a Kubernetes platform.

Statelessness is rarely complete

Session data in memory, uploaded files on the local filesystem, a cron job that may only run on exactly one instance: remnants like these prevent horizontal scaling or a simple pod restart. They go unnoticed in normal operation and turn into an incident at the first node failure.

Configuration and secrets get mixed up

Reading configuration from the environment is well understood. That credentials follow a different lifecycle than feature flags often is not. Secrets need rotation, auditability, and a backing system that is not the same Git repository.

Clean shutdown is overlooked

Kubernetes sends SIGTERM and waits for a limited period. Applications that ignore this signal cut off in-flight requests. Every deployment, every rescheduling and every node rotation then produces errors whose cause appears in no metric.

A short self-assessment

The following questions can be answered without any analysis tooling and reliably show where an application stands:

  • Can any instance be terminated at any time without a user noticing?
  • Does the same image run in every environment, differing only by configuration?
  • Does the API definition exist independently of the code, versioned and reviewable?
  • When something fails in production, can you reconstruct what happened without access to the container?
  • Is a call between two internal services verified, or assumed to be trustworthy?

If you can answer all five with yes, you have the most important prerequisites in place.

Conclusion

The twelve factors describe how an application must be built for a platform to be able to operate it at all. The three added factors describe what else is needed for it to stay manageable inside a distributed system: a dependable interface, observability from within, and security as a default assumption rather than an exception. The CNCF Cloud Native Maturity Model puts both in a wider frame and shows what becomes standard with the step into production.

The factors are not a certificate you achieve but a checklist that helps with every architectural decision. Meeting them moves complexity out of the application and into the platform, and with it, responsibility.

kloudease takes on the platform side of this responsibility as a fully managed cloud-native environment: Kubernetes with observability, secrets management, policy enforcement and backup & recovery, the same on every cloud and without vendor lock-in. The closer your application is to the 15 factors, the more the platform takes off your hands. And if you want to hand over operating the application as well, SREaaS is the next step.

More articles

All blog posts