{
  "schema_version": "22-factor.catalog/v1",
  "edition": "2026.3",
  "source": {
    "repository": "https://github.com/22-factor-apps/22-factor-apps.github.io",
    "release": "v0.5.0"
  },
  "factors": [
    {
      "number": 1,
      "numeral": "I",
      "slug": "codebase",
      "title": "Codebase",
      "tagline": "Make every deploy traceable to one authoritative source history",
      "commandment": "Map every deploy to one authoritative source history.",
      "boundary": "This requires traceable release identity, not one repository per service or a ban on monorepos.",
      "class": "durable-original",
      "category": "Source",
      "reading_minutes": 4,
      "litmus_test": "Pick any running instance. Can an engineer identify one immutable source revision, rebuild its artifact without private workstation state, and explain every other codebase that contributed through pinned dependencies? If the answer requires guessing a branch, asking who last copied a file, or checking an unversioned server directory, the application does not have an authoritative codebase yet. Modernized from Factor I of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/codebase"
    },
    {
      "number": 2,
      "numeral": "II",
      "slug": "dependencies",
      "title": "Dependencies",
      "tagline": "Declare, resolve, verify, and isolate every dependency",
      "commandment": "Declare, lock, verify, and isolate every build and runtime dependency.",
      "boundary": "A manifest alone is not reproducibility, and vendoring alone is not integrity.",
      "class": "durable-original",
      "category": "Build",
      "reading_minutes": 5,
      "litmus_test": "Start from a minimal clean builder with only the declared bootstrap toolchain. Can it resolve the locked graph, verify every fetched input, and build without reading globally installed packages or mutable tags? Then remove network access and rebuild from the captured inputs. An unexpected fetch or a changed artifact reveals an undeclared dependency or non-hermetic build. Modernized from Factor II of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/dependencies"
    },
    {
      "number": 3,
      "numeral": "III",
      "slug": "config",
      "title": "Configuration",
      "tagline": "Keep deploy-specific values out of immutable application artifacts",
      "commandment": "Build without deploy-specific values; bind validated configuration at release or runtime.",
      "boundary": "External configuration is not unversioned configuration, and secrets are not ordinary environment variables.",
      "class": "durable-original",
      "category": "Runtime",
      "reading_minutes": 5,
      "litmus_test": "Could the repository become public and the released artifact be copied to another environment without disclosing a credential or rebuilding—and would the process reject an incomplete configuration before serving traffic? That test is stricter than “we use environment variables.” It checks separation, validation, secrecy, and portability together. Modernized from Factor III of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/config"
    },
    {
      "number": 4,
      "numeral": "IV",
      "slug": "backing-services",
      "title": "Backing Services",
      "tagline": "Treat every network dependency as an attached, replaceable resource",
      "commandment": "Depend on explicit service contracts; attach and replace implementations through configuration.",
      "boundary": "Replaceable means operationally swappable through a tested contract, not identical behavior from every provider.",
      "class": "durable-original",
      "category": "Architecture",
      "reading_minutes": 5,
      "litmus_test": "Can a staging attachment be replaced with a fresh compatible instance by changing configuration, running documented migration steps, and passing automated contract tests—without editing application source? Repeat the test with the service slow, rate-limited, and unavailable. Replaceability includes predictable failure, not only the happy-path handshake. Modernized from Factor IV of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/backing-services"
    },
    {
      "number": 5,
      "numeral": "V",
      "slug": "build-release-run",
      "title": "Build, Release, Run",
      "tagline": "Create once, bind configuration once, promote without mutation",
      "commandment": "Build once, identify every release immutably, and promote the same artifact unchanged.",
      "boundary": "Pipeline stages may share tooling, but artifact bytes and release identity must never blur.",
      "class": "durable-original",
      "category": "Delivery",
      "reading_minutes": 5,
      "litmus_test": "Given a production release ID, can an operator identify and verify one artifact digest, its source and build provenance, the configuration bound in that environment, and the exact prior release available for rollback? Then promote the artifact to another environment and compare digests. If any byte changes after build, the stages are not separated. Modernized from Factor V of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/build-release-run"
    },
    {
      "number": 6,
      "numeral": "VI",
      "slug": "stateless-processes",
      "title": "Stateless Processes",
      "tagline": "Execute as share-nothing processes; persist through backing services",
      "commandment": "Keep execution disposable and durable state behind explicit stateful contracts.",
      "boundary": "Stateless processes do not imply a stateless product, nor do they make local caches authoritative.",
      "class": "durable-original",
      "category": "Runtime",
      "reading_minutes": 5,
      "litmus_test": "Terminate any process between two units of work, route the next unit to a fresh instance, and verify that no acknowledged data disappears, no action is duplicated, and no user must reconnect to the same machine for correctness. If the test fails, identify the state the process implicitly owned and give it a durable home with an explicit recovery protocol. Modernized from Factor VI of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/stateless-processes"
    },
    {
      "number": 7,
      "numeral": "VII",
      "slug": "concurrency",
      "title": "Concurrency",
      "tagline": "Scale out through explicit process types and bounded work",
      "commandment": "Partition work by process type, scale horizontally, and bound every concurrency layer.",
      "boundary": "More workers are not more capacity when queues, connections, contention, or downstream limits are already saturated.",
      "class": "durable-original",
      "category": "Scale",
      "reading_minutes": 5,
      "litmus_test": "Double one process type under representative load. Does useful throughput increase without duplicate effects, runaway queueing, dependency saturation, or violation of latency and cost objectives? Then remove half the instances abruptly. Safe reassignment and bounded degradation are part of the concurrency model too. Renumbered and modernized from Factor VIII of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/concurrency"
    },
    {
      "number": 8,
      "numeral": "VIII",
      "slug": "disposability",
      "title": "Disposability",
      "tagline": "Start promptly, stop gracefully, and recover by replacement",
      "commandment": "Start ready, stop safely, and remain correct when termination is abrupt.",
      "boundary": "Graceful shutdown improves recovery; correctness must not depend on receiving it.",
      "class": "durable-original",
      "category": "Reliability",
      "reading_minutes": 5,
      "litmus_test": "Under representative traffic, terminate a random instance during startup, steady state, and shutdown. Does the service remain within its objective, preserve acknowledged work, avoid duplicate effects, and replace the instance automatically? Measure the time from scheduling to readiness and from termination signal to clean exit. Unbounded tails are operational debt. Renumbered and modernized from Factor IX of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/disposability"
    },
    {
      "number": 9,
      "numeral": "IX",
      "slug": "environment-parity",
      "title": "Environment Parity",
      "tagline": "Keep feedback fast and production behavior representative",
      "commandment": "Shorten feedback and test every production-significant difference against the real system.",
      "boundary": "Parity means risk-representative behavior, not identical hardware, data volume, or developer environments.",
      "class": "durable-original",
      "category": "Delivery",
      "reading_minutes": 5,
      "litmus_test": "For every meaningful difference between CI or staging and production, can the team name why it exists, the risk it introduces, and the automated evidence that covers that risk against the real implementation? Then compare the deployed artifact digest, dependency inventory, schema version, and policy fingerprint across environments. Any unexplained difference is parity debt. Renumbered and modernized from Factor X of the original twelve-factor methodology.",
      "url": "https://22-factor-apps.github.io/factors/environment-parity"
    },
    {
      "number": 10,
      "numeral": "X",
      "slug": "admin-processes",
      "title": "Admin Processes",
      "tagline": "Run shipped operational code through an isolated administrative control plane",
      "commandment": "Run administrative work from the shipped release in a separate trust domain through reviewed, auditable procedures.",
      "boundary": "The same release must not mean the same network, identity store, credentials, or privileges as customer-facing processes.",
      "class": "durable-original",
      "category": "Operations",
      "reading_minutes": 5,
      "litmus_test": "Can a second operator execute a high-risk task from a named release in an isolated administrative trust domain, authenticate without the customer identity system, preview its scope, obtain least-privilege access, monitor progress, and recover safely—while leaving a complete audit trail? If success depends on the original author’s laptop, memory, or standing credentials, the task is not an application process yet. Renumbered and modernized from Factor XII of the original twelve-factor methodology. The isolation model follows NIST SP 800-207 and NIST SP 800-207A: network location alone grants no trust, so network-tier separation must be paired with identity-tier policy.",
      "url": "https://22-factor-apps.github.io/factors/admin-processes"
    },
    {
      "number": 11,
      "numeral": "XI",
      "slug": "contract-first-interfaces",
      "title": "Contract-First Interfaces",
      "tagline": "Define behavior before transport and evolve it for real consumers",
      "commandment": "Specify consumer-visible behavior before implementation, then evolve contracts with consumers.",
      "boundary": "A generated schema is not a contract unless semantics, failure behavior, compatibility, and ownership are explicit.",
      "class": "modern-addition",
      "category": "Architecture",
      "reading_minutes": 6,
      "litmus_test": "Can a consumer team implement and test a correct client—including authentication, limits, retries, and failure handling—using the published contract and examples, without reading provider source or asking which undocumented behavior is “normal”? Then change the provider’s internal framework or storage model. If conforming consumers need not change, the interface is doing its job.",
      "url": "https://22-factor-apps.github.io/factors/contract-first-interfaces"
    },
    {
      "number": 12,
      "numeral": "XII",
      "slug": "secure-by-design",
      "title": "Secure by Design",
      "tagline": "Make safe behavior the default across identity, code, data, and operations",
      "commandment": "Design the safe path as the default; verify identity, privilege, inputs, abuse cases, and failure behavior.",
      "boundary": "Authentication is necessary but not sufficient: trusted networks, secure defaults, threat models, and verified deny paths all matter.",
      "class": "modern-addition",
      "category": "Security",
      "reading_minutes": 7,
      "litmus_test": "For a randomly selected sensitive operation, can the team name the protected asset, threat and abuse cases, authenticated actor, policy decision, minimum capability, input boundary, safe default, audit event, and revocation path—and prove malformed, cross-tenant, stale, and over-privileged attempts are denied safely? Then remove network-location signals from the decision. If access becomes impossible to explain without “it came from inside,” the system still has implicit trust.",
      "url": "https://22-factor-apps.github.io/factors/secure-by-design"
    },
    {
      "number": 13,
      "numeral": "XIII",
      "slug": "observability-slos",
      "title": "Observability & SLOs",
      "tagline": "Instrument user-visible behavior and connect signals to decisions",
      "commandment": "Define user-visible objectives, instrument causality, and alert only on actionable risk.",
      "boundary": "More telemetry is not more observability, and an availability target is not permission to ignore correctness or user harm.",
      "class": "modern-addition",
      "category": "Reliability",
      "reading_minutes": 7,
      "litmus_test": "Given one failed or unusually slow user operation, can an on-call engineer move from the affected SLI to a correlated trace, relevant structured events, dependency behavior, release/configuration changes, and the responsible owner—without deploying new instrumentation? Also ask what decision follows when the error budget burns too quickly. If the answer is only “look at a dashboard,” the control loop is incomplete.",
      "url": "https://22-factor-apps.github.io/factors/observability-slos"
    },
    {
      "number": 14,
      "numeral": "XIV",
      "slug": "supply-chain-integrity",
      "title": "Supply Chain Integrity",
      "tagline": "Make every artifact traceable, verifiable, and admissible",
      "commandment": "Admit only artifacts traceable to reviewed source, declared inputs, and verifiable builds.",
      "boundary": "An SBOM, signature, or provenance statement records evidence; none eliminates the need to decide what and whom to trust.",
      "class": "modern-addition",
      "category": "Security",
      "reading_minutes": 7,
      "litmus_test": "Select a production artifact by digest. Can an independent verifier prove which reviewed source and declared inputs produced it, which trusted builder ran the build, what components it contains, which policy admitted it, and whether the exact bytes have changed since publication? Then introduce an artifact from an untrusted builder or with mismatched provenance. The deployment boundary must reject it automatically.",
      "url": "https://22-factor-apps.github.io/factors/supply-chain-integrity"
    },
    {
      "number": 15,
      "numeral": "XV",
      "slug": "resilience-fault-containment",
      "title": "Resilience & Fault Containment",
      "tagline": "Assume failure, bound amplification, and preserve the critical path",
      "commandment": "Assume components fail; bound time, retries, queues, load, and blast radius, then prove recovery.",
      "boundary": "Retries, replicas, and restarts can amplify failure unless their budgets, independence, and correctness are tested.",
      "class": "modern-addition",
      "category": "Reliability",
      "reading_minutes": 7,
      "litmus_test": "Inject latency and errors into one important dependency under peak representative load. Does the application respect end-to-end deadlines, keep retries within budget, shed low-priority work, preserve correctness and tenant isolation, remain observable, and recover without a manual restart storm? If one failing dependency consumes every worker or all recovery capacity, the fault boundary is still the entire system.",
      "url": "https://22-factor-apps.github.io/factors/resilience-fault-containment"
    },
    {
      "number": 16,
      "numeral": "XVI",
      "slug": "data-lifecycle-privacy",
      "title": "Data Lifecycle & Privacy",
      "tagline": "Minimize, classify, govern, and delete data across every copy",
      "commandment": "Collect only justified data; preserve user agency; govern every copy through verifiable deletion.",
      "boundary": "Encryption protects bytes, but it does not justify collection, confer user control, or complete retention and deletion.",
      "class": "modern-addition",
      "category": "Trust",
      "reading_minutes": 7,
      "litmus_test": "Select one sensitive field. Can the team enumerate every place it or a reversible derivative flows, state why each copy exists and who can access it, then execute and verify retention expiry, subject export, and deletion—including downstream systems and backup restoration procedures? An unknown copy or manual spreadsheet breaks the chain.",
      "url": "https://22-factor-apps.github.io/factors/data-lifecycle-privacy"
    },
    {
      "number": 17,
      "numeral": "XVII",
      "slug": "infrastructure-policy-code",
      "title": "Infrastructure & Policy as Code",
      "tagline": "Declare desired state, review policy, and reconcile drift continuously",
      "commandment": "Express infrastructure and policy as reviewed desired state, then reconcile drift within explicit safety bounds.",
      "boundary": "Code can reproduce mistakes quickly; controllers need scoped authority, previews, policy tests, and observable convergence.",
      "class": "modern-addition",
      "category": "Operations",
      "reading_minutes": 7,
      "litmus_test": "Can the team recreate a representative environment from reviewed desired state, detect one unauthorized manual change, show the exact policy violation and owner, then reconcile safely without using undocumented console steps or broad permanent credentials? Also stop the reconciler. The running application should remain understandable, and operators should know how long control-plane unavailability is safe.",
      "url": "https://22-factor-apps.github.io/factors/infrastructure-policy-code"
    },
    {
      "number": 18,
      "numeral": "XVIII",
      "slug": "progressive-delivery",
      "title": "Progressive Delivery",
      "tagline": "Separate deployment from exposure and expand change with evidence",
      "commandment": "Separate deployment from exposure; expand change only while evidence and abort controls hold.",
      "boundary": "A canary, flag, or staged rollout is not safe without representative traffic, decision thresholds, and a practiced stop path.",
      "class": "modern-addition",
      "category": "Delivery",
      "reading_minutes": 7,
      "litmus_test": "Before a risky release, can the team state the first exposed cohort, maximum blast radius, representative success and safety signals, observation window, automatic halt condition, authorized decision-maker, and tested rollback or roll-forward path? Then deliberately violate one guardrail in a rehearsal. Progression must stop before general exposure and leave enough evidence to explain why.",
      "url": "https://22-factor-apps.github.io/factors/progressive-delivery"
    },
    {
      "number": 19,
      "numeral": "XIX",
      "slug": "evolutionary-compatibility",
      "title": "Evolutionary Compatibility",
      "tagline": "Let consecutive versions coexist while contracts and data move safely",
      "commandment": "Change additively; let old and new versions coexist until migration and rollback are proved.",
      "boundary": "A major version number announces incompatibility; it does not make coordinated upgrades, data conversion, or deprecation safe.",
      "class": "modern-addition",
      "category": "Architecture",
      "reading_minutes": 7,
      "litmus_test": "Can the previous and next release run concurrently against the same interfaces and data while requests, events, jobs, and rollbacks move between them—without data loss, semantic ambiguity, or a synchronized consumer upgrade? Then rehearse stopping midway through the migration. The system must have one named source of truth, visible progress, and a safe resume or reversal path.",
      "url": "https://22-factor-apps.github.io/factors/evolutionary-compatibility"
    },
    {
      "number": 20,
      "numeral": "XX",
      "slug": "formal-methods-functional-core",
      "title": "Formal Methods & Functional Core",
      "tagline": "Model the states that matter; keep effects explicit and transformations total",
      "commandment": "Model critical state transitions explicitly; implement a functional core with pure transformations, immutable values, typed errors, and exhaustive cases.",
      "boundary": "Formal does not mean proving every line, and functional does not mean forbidding state or effects; apply rigor where failure matters and push effects to controlled boundaries.",
      "class": "modern-addition",
      "category": "Correctness",
      "reading_minutes": 8,
      "litmus_test": "Choose the most dangerous lifecycle and add one state, one late asynchronous result, and one invalid transition. Does the model expose the new interleavings, does the compiler or checker force every case to be reconsidered, does the invalid command leave state unchanged, and can the decision logic be replayed without real effects? If correctness still depends on remembering which booleans may coexist or which callback is “probably latest,” the system has an undocumented state machine.",
      "url": "https://22-factor-apps.github.io/factors/formal-methods-functional-core"
    },
    {
      "number": 21,
      "numeral": "XXI",
      "slug": "safe-languages-total-types",
      "title": "Safe Languages & Total Types",
      "tagline": "Eliminate ambient null and memory hazards; isolate every escape hatch",
      "commandment": "Prefer memory-safe languages and total types; make absence, failure, and invalid states explicit, and isolate every unsafe boundary.",
      "boundary": "A safe language cannot prevent incorrect requirements, authorization flaws, races, or misuse; unsafe and nullable interop still require containment, contracts, and adversarial tests.",
      "class": "modern-addition",
      "category": "Correctness",
      "reading_minutes": 8,
      "litmus_test": "Select one nullable field, one expected failure, one protocol state, and one native or unchecked boundary. Can the compiler distinguish every case, do callers handle them exhaustively, is ordinary code unable to dereference null or freed memory, and is the remaining escape hatch small enough to state and test its complete safety contract? If “we know this cannot be null” or “this pointer should still be valid” exists only in a comment or reviewer memory, the type boundary has failed.",
      "url": "https://22-factor-apps.github.io/factors/safe-languages-total-types"
    },
    {
      "number": 22,
      "numeral": "XXII",
      "slug": "sustainable-operation",
      "title": "Sustainable Operation",
      "tagline": "Reduce energy, carbon, water, and hardware per unit of useful work",
      "commandment": "Deliver useful work with less energy, carbon, water, and hardware—without exporting harm.",
      "boundary": "Offsets and renewable claims do not replace demand reduction, efficient code, durable hardware, or honest lifecycle accounting.",
      "class": "modern-addition",
      "category": "Efficiency",
      "reading_minutes": 7,
      "litmus_test": "Can the team name its functional unit, measurement boundary, energy and carbon intensity trend, hardware-utilization signal, largest sources of unnecessary work, and the reliability/privacy constraints on shifting or reducing demand—then show one verified improvement in both intensity and absolute impact where growth permits? If the only evidence is the cloud provider’s sustainability page, the workload itself is still unmeasured.",
      "url": "https://22-factor-apps.github.io/factors/sustainable-operation"
    }
  ]
}
