Twelve-Factor Apps, What Still Holds and What Changed
A service runs perfectly on one long-lived server. Its dependencies came from a package installed by hand months ago. Its configuration lives in a file beside the source. User sessions sit in process memory. Startup compiles the application, and logs disappear into a host directory that nobody remembers to collect.
The next deployment replaces that server. Startup fails on the missing package. Rollback rebuilds different bytes. Adding a second instance signs users out at random. The team has source code, but it does not have a reproducible application.
The Twelve-Factor App methodology attacks this class of failure. It replaces hidden machine assumptions with an explicit contract between an application and the platform that builds, configures, runs, and observes it.
What Twelve-Factor is
Twelve-Factor is a methodology for building service applications that can move between execution environments, deploy predictably, scale through additional processes, and keep development close enough to production to catch meaningful differences early.
It is language-neutral. It does not require microservices, containers, Kubernetes, or a particular cloud. A modular monolith can follow the factors. A Kubernetes deployment can violate nearly all of them.
The original methodology is also not a complete production-readiness standard. It says little about identity, authorization, software supply chains, disaster recovery, service-level objectives, or vulnerability response. Those concerns need additional frameworks and controls.
The application-platform contract
The factors make the boundary between application and platform narrow enough to inspect:
APPLICATION source + declared dependencies | | build v immutable artifact | +-----------+-----------+ | | | v v v web worker admin | | | +-----------+-----------+ | config + attached resources + process signals | v PLATFORM scheduling + routing + secrets + telemetry collectionThe application declares what it needs, accepts deploy-specific configuration, exposes process entry points, and treats attached services as resources. The platform supplies configuration, starts processes, routes traffic, sends lifecycle signals, and collects event streams.
The running example throughout this topic is an order service with three process types:
- Web: Accepts HTTP requests and persists orders.
- Worker: Consumes queued work and applies retry-safe effects.
- Admin: Runs bounded tasks such as database migrations from the same release.
One service, three ecosystems
The examples implement one contract in three public repositories. Each tagged release is runnable without cloud credentials and exposes the same web, worker, and admin responsibilities through its native toolchain.
| Ecosystem | Tested release | Process commands | Local port | Deterministic check |
|---|---|---|---|---|
| TypeScript | v1.0.2 | npm run start:web, npm run start:worker, npm run admin -- migrate --target 001 | 3101 | npm run verify |
| Python | v1.0.2 | web, worker, admin migrate --target 001 | 3102 | uv run python scripts/check_twelve_factor.py |
| Go | v1.0.3 | orders web, orders worker, orders admin migrate --target 001 | 3103 | ./scripts/check-twelve-factor.sh |
All three accept POST /v1/orders, require an Idempotency-Key, and return accepted work through GET /v1/orders/{orderId}. The request has customerId and amountCents. The amountCents value is an integer from 1 through 99. PostgreSQL stores the order schema from db/migrations/001_orders.sql, and Redis carries jobs through orders.v1.
The configuration boundary uses the same names in every implementation: DATABASE_URL, REDIS_URL, RELEASE_ID, APP_HOST, PORT, WORKER_CONCURRENCY, SHUTDOWN_GRACE_MS, and TELEMETRY_MODE. Language-specific defaults explain the three local ports, while the behavior and failure contract stay aligned.
The twelve factors at a glance
Each factor answers a failure mode. The modern reading preserves that intent while replacing dated mechanisms where the platform contract has evolved.
| Factor | Original intent | Modern reading | Proof question |
|---|---|---|---|
| Factor I: Codebase | One tracked codebase, many deploys | Trace each release to source and a build target | Can every release be traced to an exact revision? |
| Factor II: Dependencies | Declare and isolate dependencies | Lock, verify, and package the full dependency graph | Can a clean environment install without hidden host state? |
| Factor III: Config | Keep deploy config out of code | Validate deploy inputs and deliver secrets through platform boundaries | Does bad config fail safely before work starts? |
| Factor IV: Backing services | Treat services as attached resources | Inject endpoints and verify provider contracts | Can an attachment change without a code edit? |
| Factor V: Build, release, run | Keep stages separate | Promote one immutable, attributable artifact | Can the same artifact roll forward or back without rebuilding? |
| Factor VI: Processes | Run stateless, share-nothing processes | Put durable state outside replaceable instances | Can an instance disappear without losing required state? |
| Factor VII: Port binding | Export services through a bound port | Expose a self-contained invocation contract | Can the platform start and route the service directly? |
| Factor VIII: Concurrency | Scale through the process model | Scale workload types independently with bounded work | Can web and worker capacity change independently? |
| Factor IX: Disposability | Start fast and stop gracefully | Coordinate readiness, draining, timeouts, and retries | Can the platform stop an instance without corrupting work? |
| Factor X: Dev/prod parity | Keep environments close | Test production-significant contracts at the cheapest faithful layer | Are meaningful differences known and exercised? |
| Factor XI: Logs | Emit logs as event streams | Write structured events and correlate logs, metrics, and traces | Can an operator reconstruct a failure outside the instance? |
| Factor XII: Admin processes | Run one-off tasks with the release | Use bounded, attributable commands with the same code and config | Can an admin action be tied to an identity and release? |
The detailed sections use the same sequence: original principle, failure prevented, modern reading, implementation evidence, and an audit question.
Factor I: Codebase
Original claim: Factor I defines one codebase tracked in revision control with many deploys. A deploy is a running instance of the application in an environment such as production or staging.
Failure mode: A service assembled from copied directories, untracked server patches, or several unrelated source roots has no authoritative history. Teams cannot answer which code produced a running release or reproduce it after a machine fails.
Modern reading: Treat the deployable application as the unit of identity. A monorepo can contain several applications when each has an explicit build target and release history. Several repositories can contribute libraries to one application when dependency versions make the resulting source graph reproducible. Repository count is less useful than the path from release to revision.
Verify it: Pick a running web, worker, and admin process. Recover the application name, release identifier, source revision, and build target for each. All process types in one release should point to the same application revision. See Factor I: Codebase examples in TypeScript, Python, and Go.
Factor II: Dependencies
Original claim: Factor II requires explicit dependency declaration and isolation. The application cannot rely on a library or executable merely because the host operating system happens to provide it.
Failure mode: An undeclared package works on a developer laptop and fails in a clean build. A floating version resolves to different code during rollback. A runtime artifact reaches a package registry during startup and becomes unavailable when the registry or network is down.
Modern reading: A manifest declares direct dependencies. A lockfile records the resolved graph. Isolation keeps the process from importing host packages by accident. Clean installation and artifact inspection prove completeness. Integrity verification and signed provenance strengthen the supply chain, but they extend beyond the original claim.
Verify it: Install and test in an empty environment with only the manifest and lockfile available. Confirm the runtime artifact contains every required dependency and starts without compiler or registry access. See Factor II: Dependencies examples in TypeScript, Python, and Go.
Factor III: Config
Original claim: Factor III keeps values that vary between deploys out of source code. Its test is blunt and useful: the codebase should be publishable without exposing credentials or environment-specific configuration.
Failure mode: A database URL compiled into the artifact forces a rebuild for every environment. A credential committed beside source leaks through history. Scattered string lookups let an invalid value survive until the first request reaches a rarely used path.
Modern reading: Source code owns the configuration schema, defaults, and validation rules. The deployment supplies values through environment variables, mounted files, secret stores, or identity-based access. Configuration groups by independent operational concern rather than named environment bundles. Secret delivery and application configuration meet at the schema boundary, but secret material never belongs in the schema or error output.
Verify it: Start with missing and malformed values. The process should reject them before readiness without printing secret contents. Change a valid deploy setting without rebuilding the artifact. See Factor III: Config examples in TypeScript, Python, and Go.
Factor IV: Backing services
Original claim: Factor IV treats databases, queues, caches, object stores, and external APIs as attached resources. The application receives connection details through configuration instead of assuming a service lives on the same host.
Failure mode: Code embeds a production hostname, imports a provider throughout the domain layer, or depends on a daemon installed beside the application. Replacing an attachment then requires source edits and a broad rewrite.
Modern reading: Construct provider clients at the application boundary and pass narrow interfaces inward. A URL can make attachment replaceable, but it cannot make different products semantically equivalent. Transaction behavior, delivery guarantees, consistency, limits, and failure responses still need contract tests.
Verify it: Point a release at a fresh compatible resource without editing source. Run the same contract suite against both attachments and confirm that an incompatible provider fails visibly. See Factor IV: Backing services examples in TypeScript, Python, and Go.
Factor V: Build, release, run
Original claim: Factor V separates build, release, and run. Build converts source into an executable artifact. Release combines that artifact with deploy configuration. Run starts processes from the selected release.
Failure mode: Startup installs dependencies, compiles source, or applies unversioned patches. Two starts of the same nominal release can produce different bytes. Promotion rebuilds from source, and rollback cannot recover the artifact that previously ran.
Modern reading: Build once, identify the artifact by an immutable digest, attach provenance and source revision, then promote those bytes. A release adds deploy configuration and its own identifier without mutating the artifact. Database migrations are explicit admin work, not a hidden side effect of every process start.
Verify it: Promote one artifact digest through two environments with different release configuration. Block network access to source and package registries at runtime. Roll back by selecting the prior release without invoking a build. See Factor V: Build, release, run examples in TypeScript, Python, and Go.
Factor VI: Processes
Original claim: Factor VI runs the application as stateless, share-nothing processes. Durable state belongs in a backing service that outlives any one process.
Failure mode: Sessions live in web-process memory, uploads live on an instance filesystem, or worker retries rely on an in-memory completed set. Routing a request elsewhere loses state. Restarting an instance erases accepted work or repeats a business effect.
Modern reading: Process memory remains useful for bounded caches and active work, but correctness cannot depend on it surviving. PostgreSQL, object storage, and queues hold durable state. Idempotency keys and database constraints protect effects that may be retried after an ambiguous failure.
Verify it: Accept an order, terminate that instance, and read the order through another instance. Deliver the same job twice and observe one durable effect. See Factor VI: Processes examples in TypeScript, Python, and Go.
Factor VII: Port binding
Original claim: Factor VII exports an HTTP service by binding to a port. The application includes the server it needs instead of relying on a web server injected into the runtime environment.
Failure mode: The service depends on an undeclared host server, assumes one fixed port, or confuses its internal listener with its public URL. The same artifact cannot run twice on one host or move cleanly between a laptop, container, and scheduler.
Modern reading: A network process owns a self-contained listener and binds an injected address and port. The platform supplies discovery, public routing, and any edge proxy. Workers, scheduled jobs, message consumers, and function handlers have non-HTTP invocation contracts, so they do not open a port merely to satisfy the factor.
Verify it: Start two instances of the same artifact on different ports and route traffic to both. No framework-specific server should be installed on the host. Confirm that web, worker, and admin process types each expose the invocation contract their workload needs. See Factor VII: Port binding examples in TypeScript, Python, and Go.
Factor VIII: Concurrency
Original claim: Factor VIII scales an application through the process model. Named process types represent different workloads, and the platform changes the number of processes for each type.
Failure mode: One opaque process handles HTTP, scheduled work, and queue consumption. A traffic spike scales unrelated work, while an unbounded worker accepts more jobs than its database, memory, or downstream APIs can sustain.
Modern reading: Scale the web and worker fleets independently, then bound concurrency inside each process. Queue depth, processing latency, and resource saturation inform worker replica count. Backpressure protects backing services because horizontal scaling can multiply database connections and outbound requests faster than it improves throughput.
Verify it: Increase worker replicas without changing the web fleet. Confirm the queue drains faster, each worker respects its concurrency limit, and total work stays within database and downstream capacity. See Factor VIII: Concurrency examples in TypeScript, Python, and Go.
Factor IX: Disposability
Original claim: Factor IX makes processes easy to start and stop. Startup is fast, termination is graceful, and sudden death does not corrupt the system.
Failure mode: A process advertises readiness before its dependencies work, continues accepting requests after termination begins, or abandons a job after producing an external effect but before acknowledging it. Slow startup delays recovery, while unsafe retry duplicates business actions.
Modern reading: Startup, readiness, liveness, and shutdown are separate contracts. A terminating instance removes readiness, stops new work, drains within a deadline, closes resources, and exits before the platform’s grace period. Idempotency and retry safety remain necessary because hard kills bypass graceful shutdown.
Verify it: Measure time to readiness. Send termination during an HTTP request and a queued job, then confirm readiness fails first, accepted work finishes or is retried safely, and the process exits within its deadline. Force-kill a worker to test the path that signal handlers cannot protect. See Factor IX: Disposability examples in TypeScript, Python, and Go.
Factor X: Dev/prod parity
Original claim: Factor X narrows three gaps: the time between writing and deploying code, the people who write and deploy it, and the tools or backing services used in each environment.
Failure mode: A change waits weeks for release, passes from developers to a separate operations group without shared ownership, or runs against a substitute whose transaction and query behavior differ from production. The first faithful test happens after deployment.
Modern reading: Parity means production-significant contracts match, not that every environment is identical. Unit tests cover pure behavior. Disposable integration environments exercise the real database and queue types. Staging or controlled production checks cover identity, topology, scale, network policy, and failure modes that a laptop cannot reproduce honestly.
Verify it: Inventory every deliberate difference across local, CI, staging, and production. Name the behavior it can change, the test layer that covers it, and the owner of that evidence. Track how quickly a merged change reaches production and whether its authors can observe the result. See Factor X: Dev/prod parity examples in TypeScript, Python, and Go.
Factor XI: Logs
Original claim: Factor XI treats logs as event streams. The application writes each event without managing log files, routing, retention, or final storage.
Failure mode: A process writes rotating files to its local filesystem, sends directly to one vendor, or emits plain text without service and release identity. Operators enter a dying instance to reconstruct a request and lose the evidence when that instance disappears.
Modern reading: Standard output and standard error remain the collection boundary for containers. Structured events carry timestamp, severity, service, release, request, and trace fields. Metrics and traces answer questions that logs cannot, while the platform owns collection, sampling, routing, retention, and access policy. Sensitive values are redacted before emission.
Verify it: Submit one failing request and reconstruct its path from the external event stream using release, request, and trace identifiers. Repeat with a synthetic sensitive marker and confirm it never reaches collected output. See Factor XI: Logs examples in TypeScript, Python, and Go.
Factor XII: Admin processes
Original claim: Factor XII runs one-off administration from the same codebase, configuration, dependency graph, and release as the application’s long-running processes.
Failure mode: An operator runs a migration from a stale checkout with local tools and broad credentials. The command has no bound, no release identity, and no durable record connecting its actor, target, and result.
Modern reading: Package narrow admin commands in the normal artifact and run them as bounded jobs. Give each invocation short-lived identity, least privilege, a timeout, resource limits, concurrency policy, and audit evidence. Restartable migrations are safer than an unrestricted production shell or interactive REPL.
Verify it: Run the migration from the production artifact in a non-production environment, interrupt it, and retry it. Record the actor or workload identity, exact command, release digest, target, start and end times, and result. Confirm the admin identity cannot perform unrelated runtime actions. See Factor XII: Admin processes examples in TypeScript, Python, and Go.
Audit the factors by breaking assumptions
A document review can show intent, but it cannot prove runtime behavior. Start with one observable question for each factor, then inject the smallest safe failure that could disprove the claim.
| Factor | Observable audit question | Failure exercise |
|---|---|---|
| Factor I: Codebase | Can each web, worker, and admin process report the same release and source revision? | Deploy an artifact with mismatched revision metadata and require the release gate to reject it. |
| Factor II: Dependencies | Can a clean environment install, test, and start from only committed manifests and locks? | Empty the dependency cache and block undeclared global tools during the build. |
| Factor III: Config | Does invalid configuration fail before readiness without exposing its value? | Remove DATABASE_URL, corrupt PORT, and place a synthetic sensitive marker in a rejected value. |
| Factor IV: Backing services | Can an attachment move to a fresh compatible endpoint without a source edit? | Replace PostgreSQL or Redis with an unavailable endpoint, then a fresh valid instance, and inspect both paths. |
| Factor V: Build, release, run | Does promotion and rollback select existing artifact bytes without rebuilding? | Block package registries at runtime and attempt rollback by digest after the source branch changes. |
| Factor VI: Processes | Does accepted state survive instance loss and repeated delivery? | Terminate the accepting web process, restart elsewhere, and deliver the same order job twice. |
| Factor VII: Port binding | Can the same artifact bind a supplied address and port without a host-installed server? | Start two copies on different ports, then occupy one port and require a visible startup failure. |
| Factor VIII: Concurrency | Can web and worker capacity change independently while work remains bounded? | Increase worker replicas and queue depth while holding the per-worker limit and database budget fixed. |
| Factor IX: Disposability | Does readiness drop before intake stops, and does shutdown meet its deadline? | Send termination during active HTTP and worker work, then repeat with a hard kill. |
| Factor X: Dev/prod parity | Is every production-significant difference owned by a faithful test layer? | Swap a local fake for the production database type and run the same contract suite. |
| Factor XI: Logs | Can an operator reconstruct one failure from external events without entering the instance? | Trigger a traced failure, terminate the process, and search collected output by release, request, and trace identifiers. |
| Factor XII: Admin processes | Can each one-off action be tied to its actor, release, target, duration, and result? | Run an unsupported migration target and require bounded failure with no unrestricted shell or broad authority. |
Record the starting state, injected fault, expected observation, actual observation, and cleanup result. A passing agent explanation is not evidence. The test output, artifact identity, event stream, database state, and process exit behavior are the evidence.
Repository-level AI harnesses
Each reference repository separates guidance from enforcement. The root instructions give every task the application contract. The skills provide a focused Twelve-Factor review workflow for Codex and Claude. The repository-owned check remains the authority because it runs without either agent.
Codex reads repository AGENTS.md instructions before work and can load repository skills from .agents/skills. The official AGENTS.md guide and official skills guide describe those discovery rules. A SKILL.md can guide factor analysis, focused checks, and reporting, but executable tests must decide whether a contract passed.
Claude Code reads project instructions from CLAUDE.md and project skills from .claude/skills. Anthropic’s official project-memory guide recommends importing an existing AGENTS.md from CLAUDE.md when both tools share a contract. Its official skills guide documents project skill discovery and description-based activation. These files guide behavior; repository checks enforce the result.
TypeScript harness at v1.0.2
Root AGENTS.md, root CLAUDE.md, Codex skill, Claude skill, factor checklist, and check-twelve-factor.mjs.
Python harness at v1.0.2
Root AGENTS.md, root CLAUDE.md, Codex skill, Claude skill, factor checklist, and check_twelve_factor.py.
Go harness at v1.0.3
Root AGENTS.md, root CLAUDE.md, Codex skill, Claude skill, factor checklist, and check-twelve-factor.sh.
Use the same evaluation shape for either agent: ask for an explicit factor review, make a related change without naming the skill, ask for an unrelated change that should not invoke it, introduce a deliberate violation, and make the deterministic check fail. Record which instructions were loaded, which factors were named, which commands ran, and whether the agent surfaced the failing evidence.
Where literal compliance misleads
The original wording describes useful application properties through mechanisms common to its era. Preserve the property when a newer mechanism provides stronger evidence. Do not stretch the wording into a rule the methodology never needed.
| Literal reading | Durable principle | Better evidence |
|---|---|---|
| One codebase forbids monorepos | A deployable application has one traceable source history | A release resolves to an exact revision and build target |
| Every configuration value must be an environment variable | Deploy-varying configuration stays outside the artifact | Validated environment values, mounted files, external stores, or workload identity can configure one unchanged artifact |
| Two attached services are interchangeable when their URLs have the same shape | Providers attach through explicit boundaries | Contract tests expose differences in transactions, consistency, delivery, limits, and failures |
| Stateless processes mean a stateless system | Replaceable processes do not own durable state | An instance can disappear while required state survives in a backing service |
| Every workload must bind a port | Each process exposes a narrow invocation contract | Servers bind listeners, while workers and jobs accept messages or commands |
| Dev and production must reproduce the same topology | Production-significant contracts need faithful tests | Every deliberate difference has a named risk, test layer, and owner |
| Writing text to stdout completes observability | The application emits externally collectable signals | Correlated logs, metrics, and traces reconstruct an outcome without entering an instance |
| Admin processes justify an unrestricted production shell | One-off work uses the release’s code and configuration | Bounded commands run with short-lived authority and durable audit evidence |
This interpretation does not weaken Twelve-Factor. It makes each claim testable against the application-platform contract instead of a preferred tool.
Official modernization status
Status checked September 8, 2026: The official repository uses
nextas its default development branch. Its README says this work is intended to replace the hosted text when maintainers agree it is complete. 12factor.net still presents the original twelve factors. The work below is proposed, not adopted canon.
The modernization effort keeps the narrow application-platform interface at its center. Its vision separates factors, concrete examples, and broader guidance so a durable requirement does not become tied to one platform mechanism.
| Official work | State on September 8, 2026 | Direction under discussion |
|---|---|---|
| Issue 3: Logs | Open | Replace a stdout-only reading with standards-based telemetry and correlation |
| Issue 4: Config | Open | Permit mounted and externally supplied configuration or secrets while preserving separation from code |
| Issue 9: Identity | Open | Make short-lived workload identity part of the application-platform contract |
| Pull request 32: Processes | Open | Combine related process guidance, including one-off administration |
| Pull request 34: Identity | Open | Move admin guidance into Processes and use Factor XII for workload identity |
| Pull request 40: Facets | Open | Group factors by the operating properties they enable |
| Pull request 33: Dynamic config | Closed without merge | Proposed a reference from an environment value to an external dynamic-config source |
The Identity proposal is the largest structural change. It depends on the process consolidation in pull request 32, then proposes short-lived credentials supplied at runtime and scoped to an audience or backing service. That model separates workload identity from static application configuration. Until the pull request merges and the hosted method changes, it remains a design proposal.
The facets proposal is a reading aid, not four new factors. It asks what operating property a group of factors makes possible:
Continuously Deployable codebase + dependencies + config + build/release/run + disposability + dev/prod parity
Configurable config + backing services + build/release/run + parity
Scalable backing services + processes + port binding + concurrency + disposability
Observable process and service boundaries + telemetryA team could use these facets to find a weak property across several factors. It should not report them as a replacement list while pull request 40 remains open.
Independent extension models
There is no single accepted “extended Twelve-Factor App.” Later authors reorder the original factors, add production concerns, or move the discussion from an application to a whole service platform. Compare them by the gap they address instead of combining them into an invented canon.
Hoffman’s reordered 15-factor model
Kevin Hoffman’s 2016 book, Beyond the Twelve-Factor App, revises and reorders the model for cloud-native applications. Calling it the original twelve plus three hides those changes. Its sequence is:
- One Codebase, One Application
- API First
- Dependency Management
- Design, Build, Release, Run
- Configuration, Credentials, and Code
- Logs
- Disposability
- Backing Services
- Environment Parity
- Administrative Processes
- Port Binding
- Stateless Processes
- Concurrency
- Telemetry
- Authentication and Authorization
API First makes the service contract a design input. Telemetry expands operational evidence beyond log streams. Authentication and Authorization makes trust explicit. The reordered sequence also places design in the release lifecycle and credentials beside configuration, so use Hoffman’s framework as an independent revision rather than an official amendment.
IBM’s seven missing factors
IBM engineer Shikha Srivastava’s 2019 proposal, 7 Missing Factors from 12-Factor Applications, adds factors XIII through XIX for containerized microservices on Kubernetes and enterprise platforms.
| Number | Factor | Production concern |
|---|---|---|
| XIII | Observable | Operational visibility beyond emitted log streams |
| XIV | Schedulable | Resource and placement requirements the platform can act on |
| XV | Upgradable | Safe evolution of code, dependencies, interfaces, and persistent data |
| XVI | Least privilege | Minimum authority for users, workloads, and components |
| XVII | Auditable | Durable evidence of operational and security-relevant actions |
| XVIII | Securable | Protection across development, delivery, and runtime boundaries |
| XIX | Measurable | Attributable resource use, cost, and delivered value |
This is best read as an enterprise production-readiness extension. It reaches beyond application packaging into scheduling, governance, cost, and platform operations. Its categories also overlap: least privilege and auditability support security, while measurement and observability can share instruments without answering the same questions.
A CNCF-hosted 2022 reassessment
The CNCF-hosted guest post Twelve-factor app anno 2022 distinguishes application-level properties from service-level properties. Source layout and dependency declarations largely belong to the built application. Scheduling, routing, rollout, and some configuration behavior emerge from the application plus deployment definitions and platform controllers.
That distinction prevents a common review error: crediting application code for a platform control, or blaming code for a missing platform contract. The post also identifies security and automated testing as clear omissions. Security should influence every relevant boundary, while tests need to cover units, components, integrations, and end-to-end behavior at the appropriate application or service layer. This is a guest reassessment hosted by CNCF, not official CNCF policy or a replacement standard.
NGINX amendments as historical prior art
The official modernization repository lists NGINX’s microservices amendments as prior art. The original article is no longer available at its former location. The repository preserves an archived 58-page microservices reference architecture deck that discusses API routing, service discovery, load balancing, security, resilience, and health checks.
Those ideas helped move the conversation toward service-level architecture, but the surviving source does not justify reconstructing a definitive numbered NGINX factor list. Treat it as historical influence with a limited primary record.
Where the extensions overlap
The useful result is not a longer checklist. It is a map from a missing concern to the canonical boundary it strengthens and the separate framework it may require.
| Modern concern | Proposal families | Nearest canonical home | Practical treatment |
|---|---|---|---|
| API contracts | Hoffman, NGINX | Backing services, port binding | Design interfaces first and test compatibility across versions and providers |
| Telemetry and observability | Hoffman, IBM, CNCF, issue 3, facets proposal | Logs | Keep event streams, then add correlated metrics, traces, profiles, and operating outcomes |
| Workload identity and authorization | Hoffman, IBM, issue 9, pull request 34 | Config, backing services | Supply short-lived identity at runtime and authorize each intended audience |
| Scheduling and resource contracts | IBM | Concurrency, disposability | Declare resources, placement, bounded work, backpressure, and termination behavior |
| Safe upgrades | IBM | Build/release/run, admin processes | Test interface and schema compatibility, progressive rollout, migration, and rollback |
| Audit evidence | IBM | Logs, admin processes | Record who or what acted, against which release and target, under which authority |
| Security and least privilege | IBM, CNCF, Hoffman | Every factor | Apply threat-driven controls throughout and use a complete secure-development framework |
| Measurement and cost attribution | IBM | Concurrency, telemetry | Connect resource consumption to service outcomes without equating activity with value |
| Automated testing | CNCF | Dependencies, parity, release lifecycle | Prove contracts and failure behavior at the cheapest faithful layer |
What the factors still do not settle
Twelve-Factor gives an application a clean operational boundary. It does not provide a complete production, security, reliability, or data-management system. A review should name these gaps rather than award a compliance score that hides them.
| Missing concern | Questions Twelve-Factor does not answer | Complementary direction |
|---|---|---|
| Identity and authorization | Which user or workload may call which resource, with what scope, lifetime, and revocation path? | Workload identity, service authorization, least privilege, and policy tests |
| Secure development | How are threats identified, vulnerabilities handled, secrets scanned, and security requirements verified? | NIST Secure Software Development Framework |
| Software supply chain | Who built the artifact, from which inputs, and what proves it reached deployment unchanged? | SBOMs, trusted builders, attestations, verification policy, and SLSA provenance |
| Health and resources | When is a process ready, when should it restart, and how much CPU, memory, storage, or downstream capacity may it consume? | Startup, readiness, liveness, drain, resource, quota, and backpressure contracts |
| Data lifecycle | How do schemas evolve, backups restore, records expire, residency rules hold, and regions recover? | Migration compatibility, restore tests, retention policy, consistency decisions, and recovery exercises |
| Network security | Where is transport authenticated, which egress is allowed, and how are abusive or unexpected calls contained? | TLS boundaries, segmentation, service policy, rate limits, and denial-of-service controls |
| Reliability | What availability and latency are promised, how much failure is acceptable, and when should the system shed load? | Service-level objectives, error budgets, capacity tests, load shedding, and regional recovery |
| Delivery governance | Who may promote or roll back, which evidence gates a release, and how are risky changes introduced safely? | Policy checks, separation of duties, progressive delivery, compatibility gates, and audited rollback |
OpenTelemetry, SLSA, NIST SSDF, and platform-specific contracts complement Twelve-Factor because they answer different questions. They do not need to be renamed as more factors to belong in the same engineering review.
References
- The Twelve-Factor App
- Official project context: Narrow Conduits and the Application-Platform Interface, Evolving Twelve-Factor, and the
nextmodernization branch - Independent extensions: Beyond the Twelve-Factor App, IBM’s seven missing factors, the CNCF-hosted reassessment, and the archived NGINX microservices deck
- OpenTelemetry signals
- SLSA provenance
- NIST Secure Software Development Framework
Related topics
- Docker, the artifact and process boundary used by the reference services
- Kubernetes, one platform that can schedule, route, configure, and stop those processes
- GitOps, reconciliation and release promotion after the application contract is defined
- Secrets, keys, and tokens, credential types and secure delivery into deploy configuration
- Scalability, capacity, bottleneck, partitioning, and replication models beyond process concurrency