12-Factor Apps in Kubernetes: A Comprehensive Guide for 2026

The Twelve-Factor App methodology, originally introduced by Heroku, remains a useful foundation for designing applications that are portable, scalable, maintainable, and suitable for automated deployment.

Kubernetes does not replace the Twelve-Factor methodology. Instead, it provides concrete mechanisms for implementing many of its principles: immutable containers, declarative configuration, service discovery, automated scaling, self-healing, Jobs, centralized observability, and GitOps-based deployment.

Cloud-native practices have continued to evolve, however. In 2026, building a production-ready Kubernetes application also means considering software supply-chain security, GitOps, external secrets management, event-driven autoscaling, progressive delivery, policy enforcement, and OpenTelemetry-based observability.

At Retesys, we apply these principles to cloud migration and modernization projects, DevOps transformation, and the design of scalable Kubernetes-based architectures.

This guide maps the canonical Twelve-Factor App principles to practical Kubernetes patterns and modern cloud-native practices in 2026.


1. Codebase

Concept

A Twelve-Factor application has one codebase tracked in version control, with multiple deployments of that codebase.

For microservices, this usually means that every independently deployable service has a clearly defined source-code lifecycle. That does not necessarily require one Git repository per microservice: both repository-per-service architectures and well-structured monorepos are valid.

The important requirement is that each deployable application has a clearly versioned codebase and that every deployment can be traced back to a specific source revision.

Best Practice

Use Git as the source of truth for application code and keep deployment-related artifacts under version control as well.

These artifacts commonly include:

  • Kubernetes manifests
  • Helm charts
  • Kustomize overlays
  • CI pipeline definitions
  • Argo CD or Flux configuration
  • Infrastructure-as-Code definitions

Shared application functionality should normally be distributed through explicitly versioned libraries or packages rather than by copying source code between services.

For infrastructure, tools such as Terraform, Pulumi, Crossplane, or cloud-specific Infrastructure-as-Code solutions can complement Kubernetes manifests.

Modern Approach

GitOps has become one of the most effective ways to operate Kubernetes environments.

Tools such as Argo CD and Flux continuously reconcile the desired state stored in Git with the state of Kubernetes clusters.

Avoid relying on long-lived Git branches as the primary mechanism for representing development, staging, and production environments. This frequently leads to configuration drift.

A more maintainable approach is to use a relatively simple development model—often trunk-based development with short-lived feature branches—and represent environment differences using:

  • separate GitOps directories or repositories;
  • Helm values;
  • Kustomize overlays;
  • immutable image versions or digests;
  • controlled promotion pull requests.

For example:

Kustomize directory structure for base and environment overlays

The same application version can then be promoted through these environments without rebuilding the application.


2. Dependencies

Concept

Applications must explicitly declare and isolate their dependencies instead of relying on libraries, binaries, or packages that happen to exist on the underlying host.

Containers make this principle particularly natural: everything required to run the application should be part of the immutable application image or be explicitly provided as an attached service.

Best Practice

Declare dependencies using the ecosystem's standard package-management mechanisms, such as:

  • npm or pnpm for JavaScript;
  • NuGet for .NET;
  • Maven or Gradle for Java;
  • pip, Poetry, or similar tools for Python.

Use lock files where supported to make dependency resolution reproducible.

Package registries such as JFrog Artifactory, Sonatype Nexus, Azure Artifacts, GitHub Packages, or cloud-native artifact registries can provide controlled access to internal and third-party packages.

Container images should normally be built using multi-stage builds so that build tools, compilers, and temporary files do not become part of the final runtime image.

Modern Approach

Dependency management in 2026 also includes software supply-chain security.

A production CI pipeline should typically:

  1. restore dependencies from trusted sources;
  2. build and test the application;
  3. build an immutable container image;
  4. generate a Software Bill of Materials (SBOM);
  5. scan dependencies and the image for known vulnerabilities;
  6. sign the resulting image;
  7. optionally attach build provenance or other attestations;
  8. enforce policies before allowing the image to run in production.

Tools such as Sigstore Cosign can sign container images and attestations.

For example:

cosign sign registry.example.com/orders-service@sha256:<digest>

In production, admission policies implemented with tools such as Kyverno or OPA-based policy engines can verify that only approved or signed images are deployed.

Prefer minimal runtime images and run application processes as non-root whenever possible.

Distroless images can significantly reduce the number of unnecessary runtime packages. Because they intentionally exclude shells and debugging utilities, troubleshooting should generally be performed using Kubernetes ephemeral containers:

kubectl debug pod/orders-service-7d6b9c --image=busybox

This keeps debugging tools out of production application images.


3. Config

Concept

Environment-specific configuration must be kept outside application code.

Database endpoints, API URLs, feature settings, credentials, and similar values should be supplied at runtime rather than compiled into the application or committed directly into its source repository.

Best Practice

For Kubernetes workloads:

  • use ConfigMap objects for non-sensitive configuration;
  • use Secret objects for sensitive configuration when Kubernetes-native Secrets are appropriate;
  • use dedicated external secret-management systems for higher-security environments.

For sensitive information, systems such as HashiCorp Vault or cloud-managed secret stores are preferable to storing long-lived secrets directly in Git.

Kubernetes Secrets should have encryption at rest enabled where they are used.

Access should also be restricted through RBAC and dedicated application ServiceAccounts.

Modern Approach

External secret-management integrations have become preferable to application-specific configuration servers for many Kubernetes applications.

The Secrets Store CSI Driver allows pods to mount secrets retrieved from external secret-management systems.

HashiCorp Vault, for example, provides a Secrets Store CSI integration that allows pods to consume Vault-managed secrets without embedding Vault client libraries into application code.

Another common approach is the External Secrets Operator, which synchronizes secrets from external secret stores into Kubernetes.

Whenever the underlying platform supports workload identity, prefer short-lived workload identities over static cloud credentials.

One important Kubernetes detail is that configuration update behavior depends on how configuration is consumed.

A ConfigMap mounted as a volume can eventually reflect updated content, while values injected through environment variables do not automatically change in an already running container.

For applications that must restart when configuration changes, use a controlled rollout mechanism, such as:

  • GitOps-driven rollouts;
  • a configuration checksum in the Deployment template;
  • a controller such as Reloader.

Secrets should also be rotated regularly. Dynamic or short-lived credentials are preferable to static credentials whenever the backing service supports them.


4. Backing Services

Concept

Databases, caches, object storage, message brokers, SMTP servers, third-party APIs, and similar resources should be treated as attached resources.

An application should not fundamentally care whether a backing service runs:

  • in another Kubernetes pod;
  • in another cluster;
  • as a cloud-managed service;
  • or on external infrastructure.

The connection information changes, but application code should not.

Best Practice

Provide backing-service locations and credentials through runtime configuration.

For Kubernetes-native services, use Kubernetes Service objects and DNS for discovery.

For example, an application can connect to:

postgresql://orders-db.database.svc.cluster.local:5432/orders

rather than hard-coding infrastructure-specific IP addresses.

Stateful workloads that require stable pod identities can use Kubernetes StatefulSet objects together with PersistentVolumes and, where appropriate, headless Services.

Modern Approach

Kubernetes DNS should be the default service-discovery mechanism inside a cluster.

Additional service-discovery systems such as Netflix Eureka are generally unnecessary for Kubernetes-native applications because Kubernetes already provides service registration and DNS-based discovery.

HashiCorp Consul can still be useful in hybrid environments involving Kubernetes and non-Kubernetes workloads.

For more advanced networking requirements, a service mesh such as Istio or Linkerd can provide capabilities such as:

  • workload-to-workload mTLS;
  • traffic policies;
  • retries and timeouts;
  • authorization;
  • traffic telemetry;
  • multi-cluster connectivity.

A service mesh should not automatically be added to every Kubernetes platform. Kubernetes Services are sufficient for many applications, and the additional operational complexity of a mesh should be justified by real requirements.

For traffic entering a Kubernetes platform, consider the Kubernetes Gateway API and Gateway API-compatible controllers for modern traffic-routing architectures.


5. Build, Release, Run

Concept

The Twelve-Factor methodology explicitly separates three stages:

Build transforms source code into an executable artifact.

Release combines that immutable artifact with a specific configuration.

Run executes that release in the target environment.

A production deployment should never silently rebuild application code.

Best Practice

In Kubernetes, the build artifact is normally an immutable container image.

A CI system should:

Software supply chain flow from source to container registry

The deployment configuration then references that image and defines how it should run.

Helm remains a useful mechanism for packaging and templating Kubernetes applications, but Helm is not required to implement Build, Release, Run.

Other valid approaches include:

  • plain Kubernetes manifests;
  • Kustomize;
  • Helm;
  • Kubernetes Operators.

What matters is that both the application artifact and deployment configuration are versioned and reproducible.

Modern Approach

Separate CI from CD conceptually.

CI platforms such as:

  • GitHub Actions;
  • GitLab CI/CD;
  • Jenkins;
  • Tekton;

can build and validate application artifacts.

GitOps/CD systems such as:

  • Argo CD;
  • Flux;

can then reconcile approved releases into Kubernetes.

A typical flow looks like this:

GitOps delivery flow from developer commit to Kubernetes deployment

Do not rely on mutable tags such as latest for production releases.

Prefer immutable versions or image digests:

image: registry.example.com/orders-service@sha256:...

The same artifact should move through development, staging, and production.

For applications that require safer production deployment strategies, progressive-delivery tools such as Argo Rollouts or Flagger can implement:

  • canary releases;
  • blue-green deployments;
  • automated rollout analysis;
  • controlled rollback.

6. Processes

Concept

Application processes should be stateless and share nothing.

A request must not depend on being routed back to the same pod because of state stored only in local memory or the pod filesystem.

Kubernetes pods are intentionally replaceable. A correctly designed service should continue working when any individual pod disappears.

Best Practice

Use Kubernetes Deployment objects for stateless application workloads.

Persist application state in backing services such as:

  • relational databases;
  • NoSQL databases;
  • Redis;
  • object storage;
  • message brokers.

If a workload genuinely requires stable network identities or persistent disks, StatefulSet may be appropriate.

Databases and other complex stateful platforms are also frequently managed using Kubernetes Operators or provided as external managed services.

For asynchronous communication, use message or event brokers such as:

  • Apache Kafka;
  • RabbitMQ;
  • NATS;
  • cloud-managed messaging services.

Avoid coupling services through shared in-memory state.

Modern Approach

Event-driven architecture works especially well with stateless workers.

For example, an order-processing system may consist of:

Event-driven worker topology using a queue and worker pods

The queue stores work, while individual worker pods remain disposable.

Application sessions should similarly be stored externally when they need to survive pod replacement.

Sidecars, service-mesh proxies, telemetry agents, and secret injectors may coexist with the application process, but they do not change the core principle: the application's business process itself should remain replaceable and should not depend on local persistent state.


7. Port Binding

Concept

Port Binding is the canonical seventh Twelve-Factor principle.

A Twelve-Factor application should expose its service through a port rather than depending on an external application server that is manually configured around it.

In containerized applications this model is natural: the application starts inside its container and listens on a configured network port.

Best Practice

Configure the application to listen on an explicitly defined port, preferably provided through configuration.

For example:

HTTP_PORT=8080

The application listens on that port inside its pod.

Kubernetes then provides stable access through a Service:

apiVersion: v1
kind: Service
metadata:
  name: orders-service
spec:
  selector:
    app: orders
  ports:
    - port: 80
      targetPort: 8080

Other services should communicate through the Kubernetes Service rather than directly addressing pod IP addresses.

Modern Approach

Avoid coupling applications to node-specific networking such as hostPort or hostNetwork unless a workload genuinely requires it.

For normal application services, use:

Port mapping from the application through a Kubernetes Service and gateway to the client

For external HTTP, HTTPS, or gRPC traffic, a Gateway API-compatible gateway can expose the service without changing the application itself.

Environment-specific DNS names, TLS certificates, load balancers, and routing policies remain infrastructure concerns rather than application-code concerns.


8. Concurrency

Concept

The Twelve-Factor methodology recommends scaling applications through the process model.

In Kubernetes, this typically means running multiple pod replicas rather than relying on a single oversized application instance.

Different types of work can also run as independently scalable workloads—for example, API pods and background-worker pods.

Best Practice

Use Kubernetes Horizontal Pod Autoscaler (HPA) for workloads whose replica count should vary with demand.

HPA can scale based on:

  • CPU;
  • memory;
  • custom metrics;
  • external metrics.

CPU utilization alone is not always a good business indicator.

For example, an HTTP application may scale more effectively based on request rate, while a worker may scale based on queue depth.

Correct Kubernetes resource requests are particularly important because autoscaling decisions often depend on them.

Vertical Pod Autoscaler (VPA) can help recommend or adjust resource requests for workloads whose resource requirements are difficult to estimate.

Because some VPA modes can recreate pods when changing resource assignments, use it with an understanding of its impact on availability.

Modern Approach

For event-driven workloads, use KEDA where appropriate.

KEDA can scale Kubernetes workloads based on external event sources such as:

  • Kafka lag;
  • RabbitMQ queues;
  • cloud queues;
  • databases;
  • monitoring systems.

This is especially useful when CPU utilization does not represent the amount of pending work.

A typical architecture becomes:

KEDA-driven scaling from queue depth to worker replicas

Some KEDA configurations can scale event-driven workers to zero when there is no pending work.

Do not blindly combine autoscalers. If HPA and VPA are both changing the same CPU- or memory-related characteristics, configure them carefully to avoid conflicting feedback loops.

Autoscaling should also include sensible minimums, maximums, stabilization behavior, and capacity planning.


9. Disposability

Concept

Processes should start quickly and shut down gracefully.

Kubernetes routinely replaces pods because of:

  • deployments;
  • autoscaling;
  • node maintenance;
  • failures;
  • scheduling changes.

An application must therefore expect termination at any time.

Best Practice

Configure Kubernetes health probes according to their intended purpose.

Startup probes determine whether an application has completed startup.

Readiness probes determine whether a pod should currently receive traffic.

Liveness probes determine whether the application is stuck badly enough that restarting it may recover the process.

Do not make liveness probes unnecessarily dependent on remote databases or third-party APIs. A temporary downstream outage should not create a cluster-wide container restart storm.

Modern Approach

Applications must correctly handle SIGTERM.

When Kubernetes terminates a pod, the application should:

  1. stop accepting new work;
  2. complete or safely abandon in-flight work;
  3. close resources;
  4. exit within the configured termination grace period.

terminationGracePeriodSeconds should provide enough time for a normal graceful shutdown without making pod termination unnecessarily slow.

preStop hooks can be useful for applications that need additional coordination, but application-native signal handling is preferable when possible.

Readiness should be used so Kubernetes removes an application instance from traffic when that instance is unable to serve requests.

For remote calls, implement resilience patterns such as:

  • explicit timeouts;
  • bounded retries;
  • exponential backoff and jitter;
  • circuit breakers.

Libraries such as Polly for .NET and Resilience4j for Java can implement these patterns.

When a service mesh is already deployed, some traffic-level retry, timeout, and circuit-breaking policies can also be implemented at the infrastructure layer.

Retries should always be used carefully because uncontrolled retries can amplify outages.


10. Dev/Prod Parity

Concept

Development, staging, and production should remain as similar as reasonably possible.

The goal is not to make every environment identical in capacity. A development cluster may have one replica while production has twenty.

The important requirement is to minimize differences in:

  • application artifacts;
  • dependency versions;
  • deployment mechanisms;
  • infrastructure definitions;
  • backing-service behavior.

Best Practice

Build an application image once.

Then promote the same image through environments:

Promotion of an immutable build digest through development, staging, and production

Do not rebuild the application separately for production.

Environment-specific differences should normally come from external configuration rather than different binaries.

Modern Approach

Use Infrastructure-as-Code and GitOps to minimize environment drift.

For example:

GitOps repository structure with base and per-environment configuration

All environments can reuse the same base deployment while applying narrowly scoped differences such as:

  • replica count;
  • resource allocation;
  • domain names;
  • external service endpoints;
  • feature configuration.

Ephemeral preview environments can also be useful for pull requests when the cost and operational complexity are justified.

The central rule remains simple:

Build once and promote the same immutable artifact.


11. Logs and Observability

Concept

The original Twelve-Factor principle says applications should treat logs as event streams.

Applications should normally write their logs to standard output and standard error instead of managing application log files themselves.

Kubernetes and the surrounding observability platform can then collect, route, store, query, and retain those events.

Best Practice

Produce structured logs whenever practical.

For example:

{
  "timestamp": "2026-08-11T15:25:18Z",
  "level": "Information",
  "service": "orders",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "message": "Order created",
  "order_id": "48127"
}

Structured data is significantly easier for log platforms to search and aggregate than arbitrary text.

A node-level log collector such as Fluent Bit or Vector can forward container logs to:

  • Elasticsearch;
  • Grafana Loki;
  • cloud logging platforms;
  • other centralized log stores.

Applications should also avoid logging credentials, tokens, personal data, or other sensitive information.

Modern Approach

Modern observability should be considered across three major telemetry signals:

Logs
Metrics
Traces

Prometheus remains a common choice for Kubernetes and application metrics.

For instrumentation and telemetry transport, OpenTelemetry has become an important cloud-native standard.

Applications can use OpenTelemetry SDKs and OTLP to produce traces, metrics, and increasingly logs through a consistent telemetry model.

An OpenTelemetry Collector can then receive and process telemetry before exporting it to observability platforms.

For example:

Telemetry flow from the application through the OpenTelemetry Collector to metrics, tracing, and logging backends

Distributed trace IDs and span IDs should be propagated between services and included in structured logs where possible.

This allows operators to move from:

Incident investigation flow from alert to metric to trace to logs

when investigating production incidents.

Tools such as Jaeger remain useful as trace backends, but application instrumentation should generally favor OpenTelemetry rather than tying application code directly to one tracing vendor.


12. Admin Processes

Concept

Administrative tasks should be executed as one-off processes rather than being built into the normal application runtime.

Typical examples include:

  • database migrations;
  • data repair;
  • data imports;
  • periodic maintenance;
  • reporting jobs.

These processes should run using the same application code and configuration model as normal application processes.

Best Practice

Use Kubernetes Job objects for one-time tasks.

For example:

apiVersion: batch/v1
kind: Job
metadata:
  name: orders-database-migration
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migration
          image: registry.example.com/orders-service@sha256:...
          args:
            - migrate

Use CronJob for regularly scheduled tasks.

Examples include:

  • cleanup operations;
  • periodic aggregation;
  • report generation;
  • synchronization.

Where possible, administrative tasks should be idempotent so that retrying a failed operation does not corrupt data.

Modern Approach

Administrative processes should be automated rather than dependent on an engineer manually entering a production container.

CI/CD or GitOps workflows can coordinate migration Jobs as part of a controlled release procedure.

For complex batch or workflow scenarios, tools such as Argo Workflows may be appropriate.

Ephemeral containers and kubectl debug are useful for troubleshooting, but they should not become the normal mechanism for production administration.

The ideal production environment minimizes manual changes that bypass version control and the deployment process.


Additional Kubernetes Best Practice: Data and Network Isolation

Data isolation appeared as Factor 7 in the previous version of this guide. It is an important microservices and Kubernetes practice, but it is not one of the canonical Twelve Factors. The canonical seventh factor is Port Binding.

Data isolation is therefore better treated as an additional cloud-native architecture and security practice.

Data Ownership

Each microservice should normally own the data that belongs to its business capability.

For example:

Service-to-database ownership diagram showing separate databases per service

The Orders service should not reach directly into Payments database tables.

Services should exchange information through:

  • APIs;
  • commands;
  • messages;
  • domain events.

This approach aligns well with Domain-Driven Design and helps prevent database-level coupling between services.

It also makes independent deployment and evolution easier.

A separate physical database is not mandatory for every small service, but logical ownership boundaries should remain clear even when infrastructure is shared.

Network Isolation

Kubernetes networking is intentionally open unless restrictions are applied.

Applications that require isolation should use Kubernetes NetworkPolicy with a networking implementation that enforces those policies, such as Cilium or Calico.

A strong approach is to start from default-deny policies and explicitly allow required communication.

Conceptually:

API boundary diagram showing database access through the API and blocked direct access

This reduces unnecessary lateral movement if one workload is compromised.

Workload Security

Network controls should be combined with workload-level security.

Use:

  • dedicated Kubernetes ServiceAccounts;
  • least-privilege RBAC;
  • non-root containers;
  • restricted Linux capabilities;
  • read-only filesystems where practical;
  • Kubernetes Pod Security Admission.

For stronger governance, policy engines such as:

  • Kyverno;
  • OPA Gatekeeper;

can validate Kubernetes resources before workloads are admitted to the cluster.

Policies can enforce rules such as:

✓ images must come from approved registries
✓ privileged containers are forbidden
✓ containers must run as non-root
✓ resource requests must be defined
✓ signed images must be used

Combined with SBOM generation, image signing, vulnerability scanning, and secret-management policies, admission controls provide an additional security boundary between CI/CD and production.


Putting the Twelve Factors Together

A modern Kubernetes delivery architecture can combine these practices as follows:

Architecture overview combining CI, GitOps, and Kubernetes runtime concerns

The important point is not to adopt every tool shown in the diagram.

A production platform should use the simplest architecture that satisfies its actual requirements.

Kubernetes-native capabilities should generally be the starting point. Additional components such as a service mesh, external secrets operator, progressive-delivery controller, or policy engine should be introduced when they solve a concrete operational, security, or architectural problem.


Conclusion

The Twelve-Factor App methodology remains highly relevant to Kubernetes in 2026, but applying it effectively requires interpreting its principles in the context of modern cloud-native engineering.

Several practices have become particularly important:

  • use Git and GitOps as sources of operational truth;
  • build immutable container images once and promote the same artifact between environments;
  • generate SBOMs, scan images, sign artifacts, and enforce supply-chain policies;
  • keep runtime configuration and secrets outside application code;
  • use Kubernetes Services and DNS as the default service-discovery mechanism;
  • treat service meshes as an advanced capability rather than a mandatory component;
  • keep application processes stateless and disposable;
  • use HPA and event-driven autoscaling such as KEDA according to workload characteristics;
  • implement startup, readiness, and liveness probes correctly;
  • handle graceful termination and distributed-system failure explicitly;
  • use OpenTelemetry-based instrumentation for modern observability;
  • execute administrative work through Jobs, CronJobs, and controlled automation rather than manual production changes;
  • enforce data ownership, network segmentation, RBAC, Pod Security, and admission policies as complementary Kubernetes security practices.

The value of Twelve-Factor architecture has never depended on a particular framework or Kubernetes tool.

Its real value is the discipline it encourages: explicit dependencies, external configuration, immutable releases, stateless processes, replaceable instances, automated operations, and clear separation between application code and infrastructure.

Combined with modern Kubernetes and cloud-native practices, these principles provide a strong foundation for building systems that are easier to deploy, scale, secure, observe, and maintain.

At Retesys, our cloud software experts can help you implement modern 12-factor app principles, migrate legacy systems to the cloud, and build scalable cloud-native applications.

Contact us today to learn how we can streamline your cloud migration journey and ensure your infrastructure is ready for the future.

Contact Us