Handover, outage, audit: three situations every application faces
You switch development partners. A server fails. Procurement at a major customer sends over a security questionnaire. Whether your software handles these three situations well is decided months before they happen, in the architecture.
Our service pages, such as the one on custom software development, say that we follow the principles of the Twelve-Factor App. This article explains what the 12-Factor App is about and what you gain from it as a client. Three guiding questions run through it:
- Handover: Can another team or another hosting provider take over your software without starting from scratch?
- Outage: Is it back up quickly after a hardware fault or a failed update?
- Audit: Can you show your data protection officer, your IT security team or procurement who changed what and when, and where the credentials are stored?
A note before we start: this is not a guide for developers. First come the definition and the twelve factors in a table, then the benefits in each of the three situations. At the end, I show how we apply this in our projects and where the methodology ends.
What is the 12-Factor App?
The 12-Factor App, originally “The Twelve-Factor App,” is a methodology of twelve rules for web applications and online services. Its goal: such applications should deploy automatically, run on modern cloud platforms and scale without major rework.
Adam Wiggins, co-founder of the cloud platform Heroku, published the methodology in 2011. According to its introduction, the contributors had been directly involved in building and deploying hundreds of apps. Through their work on Heroku, they had also indirectly witnessed how hundreds of thousands more were developed, operated and scaled.
The original text was last updated in 2017. On November 12, 2024, Heroku turned the 12-Factor App into a community-driven open-source project. The revision lives on GitHub, is licensed under CC BY 4.0 and is meant to replace the 2017 version at a later date.
The core idea is a clear division of labor between the application and the platform that runs it. The application receives its settings from the platform at startup, puts everything persistent into databases or storage services and writes its logs as a continuous stream. The platform starts it, scales it and collects the logs.
One important point for context: the 12-Factor App is not a framework, not a product and not a certification. According to the original, it can be applied in any programming language and with any combination of connected services. So you cannot buy it. You can only require it when your software is built.
A note on terms: I use the original factor names and explain each one. Some of them, such as “disposability” or “dev/prod parity,” are engineering shorthand that says little to anyone outside the field.
In short: the 12-Factor App does not dictate where your software runs. It dictates how the software has to behave so that the location stays interchangeable.
The twelve factors and their benefits at a glance
The table follows the order of the original. Six terms come up in it and throughout the rest of the article:
- Repository: the store that holds the source code and its full change history.
- Backing services: every service the application uses over the network while running, such as the database, email delivery, file storage or external APIs.
- Build and release: the build is the executable package made from code and third-party libraries. The release is that build plus the configuration of one environment, such as test or production.
- Deployment: rolling out a release to the servers.
- Instance: a running copy of the application, today usually a container: a self-contained, isolated package with everything the application needs to run.
- Process: here in the technical sense, a running program inside an instance, for example one that handles web requests or background jobs.
How to read it: the left column names the factor by its original name, the middle one states the rule in one sentence, and the right one shows the benefit for you as the client.
| Factor | What it is about | What you get out of it |
|---|---|---|
| I. Codebase | One application, one repository, from which every environment is built | Every running version can be traced back to a specific version of the code |
| II. Dependencies | Every third-party library (dependency) is declared with its exact version, and nothing on the server is silently assumed | When a vulnerability is published, you quickly know whether you are affected |
| III. Config | Settings and credentials live apart from the code and are set per environment | No passwords in the source code, new environments without code changes |
| IV. Backing services | Database, email delivery and file storage are attached only via address and credentials | Switching providers and restoring without rework |
| V. Build, release, run | Build, combine with the configuration, run: three separate steps, each release with its own identifier | You know what went live when, and you have a planned rollback path to the previous version |
| VI. Processes | Processes hold short-lived intermediate state at most, everything persistent lives in a database or storage service | If an instance fails, stored data survives |
| VII. Port binding | The application ships with its own web server and is reachable on its own port, a numbered connection point the platform forwards requests to | The same application runs locally, in test and with any provider that runs containers |
| VIII. Concurrency | More load means more processes instead of bigger servers, and web requests and background jobs run separately | You absorb traffic spikes with additional instances |
| IX. Disposability | Processes start in seconds and shut down gracefully | Fewer errors during updates and restarts, because requests in progress still complete |
| X. Dev/prod parity | Development, test and production use services of the same type and version | Fewer bugs that only show up in production |
| XI. Logs | The application emits events as a continuous stream, and the platform collects them centrally | One view across all instances, for troubleshooting and audits |
| XII. Admin processes | One-off tasks such as database migrations, i.e., changes to the database schema, use the same release as the application: same code, same configuration | Code and database schema stay in lockstep, and every migration lives as code in the repository |
Taken together, the twelve rules give your business three benefits: interchangeable development teams and providers (factors I, II, III, IV and VII), operational reliability through outages, traffic spikes and releases (V, VI, VIII, IX, X and XII), and traceability for auditors and procurement (I, II, III, V and XI). I go through them in that order.
No single factor is spectacular on its own. The effect comes from the combination: the more factors an application follows, the easier handovers, recovery and audits become.
Avoiding lock-in: team and provider stay replaceable
Lock-in, meaning a dependency that makes every switch expensive, comes in two forms: being tied to a team and being tied to a hosting or cloud provider. The architecture can take the edge off both.
When you switch teams
More than once, I have seen a company come out of a relaunch with a running system and no access to the repository. Factor I makes sure there is only one thing to hand over as far as code goes: each application has exactly one repository, and everything that runs comes from it. Whoever holds this repository holds the entire history.
Beyond the code, the handover includes the configuration for each environment and access to the database and services. To make sure the repository really is yours, we set it up in your company’s name from day one, and handover documentation is part of the delivery. Both are stated on our web app development page.
We also document architecture and deployment, and the deployment itself runs without proprietary tooling (see our guide to custom software).
Factor II adds to this: every third-party library, in developer jargon a dependency, is recorded with its exact version. A new team therefore does not have to guess which library ran in which version on which server. The original explicitly names the goal of minimizing time and cost for new developers joining the project.
Our rule here: a change of vendor must never fail because all the knowledge sits with one agency.
When you switch providers
This is where factor IV comes in: database, email delivery and file storage are attached as backing services via address and credentials only. The original’s example is swapping a self-run MySQL database for a managed service such as Amazon RDS without changing the code.
Factor III keeps settings out of the code, and factor VII has the application ship with its own web server. That is why the same application runs locally, in test and with any provider that runs containers.
There is legal tailwind, too: the EU Data Act has applied since September 12, 2025. It obliges providers of data processing services, such as cloud platforms, to remove obstacles to switching (Art. 23). After a notice period of at most two months, a transitional period of at most 30 calendar days follows (Art. 25(2)). If that is technically unfeasible, the provider can set a transitional period of up to seven months, with justification (Art. 25(4)).
From January 12, 2027, switching charges are prohibited (Art. 29(1)). In practice, though, you can only use these rights if your application is able to move.
The uncomfortable point: if you use provider-specific features deep in the code, you are locked in anyway. What stays interchangeable is whatever is attached via open, widely used technology, such as a PostgreSQL database. In my comparison of Supabase and Firebase, I put it bluntly: the exit is the actual architecture.
Interchangeability is not a contract clause. It is a property of the architecture.
Replace, don’t repair: outages, traffic spikes, releases
The second situation is the outage. Here the 12-Factor App relies on replacing rather than repairing: a broken instance is not fixed by hand, it is swapped out. Three cases show what that means in day-to-day operations.
Outage: instances are replaceable, data is not
Factor VI calls for stateless processes. Stateless means that the running application holds no persistent data, because everything persistent lives in the database or a storage service. If an instance fails, the platform starts a new one, and stored data is preserved. Our article on Keycloak hosting puts it this way: “Keycloak containers are replaceable; the PostgreSQL behind them is not.”
That is why the real effort goes into backups and into rehearsing the restore. State also hides in details: when you self-host Next.js, the cache for pre-rendered pages sits on the local disk by default. Once you run several instances, you need a shared cache, for example one based on the Redis data store.
Factor IX governs the swap itself: processes start fast and shut down gracefully when they receive a signal. Kubernetes, the widely used platform for running containers, gives an instance 30 seconds for this by default, and Google Cloud Run gives it 10 seconds before a hard stop. If you finish in-flight requests within that window, deployments and maintenance usually go through without errors.
Two conditions go with it: new instances may only receive requests once they have passed the platform’s readiness check. And background jobs must be safe to retry, so that an interrupted run does not create an order twice.
Traffic spike: more instances instead of a new architecture
For scaling, factor VIII relies on more processes, split by type of work. One example from our own projects is the commerce platform Medusa: in production it runs as a server process for requests and as a worker process for background work. That way, background jobs do not slow down web requests. Both processes share the same credentials and the same database, and a single setting determines the mode.
What it costs: hosting a typical application on Hetzner runs €20 to €50 a month, or €150 to €400 for high availability with redundant instances, plus 2 to 5 hours of support per month. Moving from a single instance to high availability requires no rewrite of the code. For operations, though, it is a project in its own right: at least two instances, a replicated database and a load balancer in front.
One limitation remains: only what is stateless scales out. The database scales differently, and usually at a higher price.
Release: small, frequent, with a planned rollback
Factor V separates three steps: build, combine with the configuration, run. Build and configuration together produce a release with a unique identifier, and that release is never changed afterward: every change creates a new release. If you use the same build in every environment, you test exactly the package that goes live.
For Keycloak upgrades, we define the rollback, meaning the way back to the previous version, in advance: a database snapshot taken right before the migration plus the built package of the old version. Beforehand, we rehearse the upgrade on a staging environment, a production-like test system with an anonymized copy of the production data.
The rollout is followed by an observation window of 30 to 60 minutes: if something shows up in that window, we roll back. After that, we fix forward, because restoring a snapshot discards every data change made since the migration.
Factor X keeps development, test and production as similar as possible. The original contrasts weeks between deployments for traditional applications with hours for a 12-factor app. DORA, Google Cloud’s research program on software delivery, concludes that speed and stability are not trade-offs.
Factor XII ties changes to the database schema to the same release as the code that needs them. In the end, one rule applies: a rollback nobody has rehearsed is not a rollback.
Security and compliance: evidence instead of assurances
First, on compliance: the GDPR demands not only protection but also proof. The controller (usually your company) must “be able to demonstrate compliance,” as the accountability principle in Art. 5(2) puts it. In Germany, NIS2, the EU cybersecurity directive, is implemented through the BSI Act (BSIG). If your company falls under it, you must document compliance with the risk management measures (Section 30(1) sentence 3 BSIG).
Management must implement and oversee these measures and take part in training regularly (Section 38 BSIG, in force since December 6, 2025). In Austria, NIS2 is implemented by the NISG 2026, which has applied since October 1, 2026. Even if your company is not covered by NIS2, regulated customers will ask you similar questions: they have to take the security of their suppliers into account (Section 30(2) no. 4 BSIG).
What auditors and procurement ask
Whether the questions come from the data protection officer, IT security or a major customer’s procurement, they tend to be similar. Some of them can be answered from the architecture. I have described what evidence procurement wants to see using a trust center page for SaaS providers as the example. The table maps typical audit questions to the factors and names the matching regulatory reference.
| Question from an audit or procurement | Answer from the architecture | Regulatory reference |
|---|---|---|
| Who changed what and when, and who approved it? | I (Codebase), V (Build, release, run), XII (Admin processes): change history, release identifier, migrations inside the release. The review record shows who approved a change | ISO 27001 A.8.32; SOC 2 CC8.1; NIS2 Art. 21(2)(e) |
| Where are passwords and API keys stored? | III (Config): outside the code, set per environment and replaceable | ISO 27001 A.5.17, A.8.9 |
| Which third-party components are in the software? | II (Dependencies): a complete list of all dependencies with exact versions | ISO 27001 A.5.21, A.8.8; NIS2 Art. 21(2)(d) |
| How fast are you back up after an outage? | IV (Backing services), VI (Processes), IX (Disposability): data only in backed-up services, instances replaceable at any time | GDPR Art. 32(1)(b) and (c); ISO 27001 A.8.13; NIS2 Art. 21(2)(c) |
| Does real data end up in test and development? | X (Dev/prod parity), III (Config): same technology, but a separate database and separate credentials per environment. A separate policy governs how real data is handled | ISO 27001 A.8.31, A.8.33; GDPR Art. 25 |
| What gets logged, and where do the logs come together? | XI (Logs): centrally collected logs from all instances | ISO 27001 A.8.15, A.8.16; SOC 2 CC7.2; HIPAA § 164.312(b) |
| Which service providers process data on your behalf? | IV (Backing services): every attached service can be read from the configuration | GDPR Art. 28; ISO 27001 A.5.19, A.5.23 |
Two notes on reading the table: all mappings are our own expert judgment. They show what a question is aiming at, not that a requirement is met. And references to ISO 27001 are to ISO/IEC 27001:2022 and its Annex A.
On the two US references: SOC 2 is an attestation report issued by an independent CPA firm under AICPA standards. Large companies ask for it most, especially those with US-based procurement. HIPAA, the US law protecting health information, covers US health plans, health care clearinghouses and health care providers, plus anyone who processes health data on their behalf, including subcontractors. Whether that applies to you is a question for your legal counsel.
Credentials and third-party libraries: two well-known gaps
The first gap: credentials in the code. In 2025, the security vendor GitGuardian found 28.65 million new hardcoded secrets in public commits on GitHub, 34 percent more than the year before. According to its annual report, 32.2 percent of internal repositories contained hardcoded credentials, against only 5.6 percent of public ones. One caveat: this is a vendor study, and GitGuardian sells tools against exactly this problem.
Factor III draws a clear line here. The litmus test from the original: could the codebase “be made open source at any moment, without compromising any credentials”?
The second gap: untracked third-party libraries. On December 11, 2021, Log4Shell, a vulnerability in a widely used Java library, led Germany’s Federal Office for Information Security (BSI) to raise its threat level to red, its highest warning level (in German). At the time, the BSI said it could not yet fully assess which products were vulnerable.
My takeaway: with a complete list of all dependencies and their exact versions, “Are we affected?” becomes a lookup for your own application instead of a search.
What the methodology does not do
To put it plainly: the 12-Factor App is neither a certificate nor a seal of approval. Under ISO 27001, what gets certified is an organization’s management system, not an application. Annex A of the standard lists 93 controls: 37 organizational, 8 people, 14 physical and 34 technological. The twelve factors touch only a small part of them, mostly technological controls.
Nor is the methodology enough for PCI DSS, the card payment industry’s security standard, or for the EU AI Act. How much of PCI DSS applies to your application depends mainly on whether card data passes through your systems or only through the payment provider.
The EU AI Act raises questions the methodology does not ask at all, such as risk categories, transparency and human oversight. What it requires of buyers is covered in The EU AI Act for Software Buyers.
Risk analysis, policies, training and contingency planning remain your company’s job, as do data protection impact assessments and keeping track of all processors. If we run operations, the data processing agreement with us is part of the project. If you run the application yourself, the technical evidence is on you too: logging, an access control policy and restore tests. I work out what that costs in my article on what Keycloak really costs.
Our role: on request, we work with your data protection officer and supply the technical documentation, for example for your records of processing activities. Your company provides the evidence to auditors, and we create the technical basis for it. We do not replace legal advice, and where requirements are higher, we recommend external security audits.
The methodology does not make software compliant. It makes sure you have answers to the technical questions, and that you can back them up.
From code to operations: how we apply this in projects
How much of this do we follow ourselves? This section only covers what we also describe publicly elsewhere, each point with the matching factor in parentheses.
From change to release
- A review for every change (I, V): Every change goes through a mandatory review by senior developers, who are also accountable for every release decision.
- Dependencies under control (II): We keep dependencies to a minimum and use lockfiles, files that pin every library to an exact version. We also use automated update and audit processes and a mandatory review for every new dependency, as described on our TypeScript agency page.
- Containers and separate configuration (III, VII): Applications we host ourselves run as Docker containers. Next.js apps, for example, are built on a standard base image, the template every container starts from. Code and configuration stay separate: each environment gets its own configuration.
- Previews and deployment with Coolify (IX, X): On Hetzner we use Coolify, an open-source deployment platform. It can create a separate preview URL for every proposed change (pull request) and ship new versions with zero downtime (Next.js on Hetzner). We decide at the start which of these features a project uses.
- Migrations as a separate step (XII): Database migrations run as a defined step before deployment (with Medusa, for instance, via medusa db:migrate), not by hand in a console on the live system. Here we read the factor more strictly than the original, which explicitly allows such a console: whatever happens only there is missing from the change history.
- Operations with a tested restore (IX): Building a self-hosted stack typically costs a one-time €5,000 to €20,000, depending on complexity. That covers infrastructure, pipelines (automated workflows for build and deployment), monitoring and backups with a restore tested at least once. After that, support typically runs 2 to 5 hours a month.
A word on the mandatory review: the original asks developers to be closely involved in deploying their code (factor X). ISO 27001, on the other hand, calls for segregation of duties in Annex A (A.5.3). A review by a second person is a common way to reconcile the two. Whether that suffices as evidence depends on your company’s management system.
What we decide per project
We choose the platform per project, as described on our tech stack page: for projects with data protection requirements, we prefer Hetzner, a German company with data centers in Germany and Finland. For projects without strict data protection requirements, the US platforms Vercel or Netlify are also an option. This website itself runs on Vercel. Both options work mainly thanks to factors III, IV and VI.
During planning, we decide which environments a project needs. Whether the tested image moves into production unchanged depends on the project: Next.js, for example, bakes settings that the browser needs into the build. One thing I will say openly: self-hosting shifts responsibility, it does not eliminate it.
Limits: where the methodology ends and how we read it in 2026
First of all: fifteen years after it was written, some of the methodology’s examples look dated, such as the tools Capistrano or Foreman. Yehuda Katz, one of the people behind the project, wrote in November 2024, when the project went open source: “while the concepts remain relevant, many of the details have started to show their age.” We see it the same way. Four points show how we read the methodology today.
Credentials: separate from the code, but not just in environment variables
Factor III recommends environment variables for credentials, too. These are values the operating system hands to a program at startup. The security initiative OWASP advises against this where other options exist: environment variables are generally accessible to all processes and can end up in logs or memory dumps. On top of that, Kubernetes stores secrets unencrypted in its internal database etcd by default.
Our recommendation: the separation of code and configuration stays. Where the sensitivity of the data calls for it and the platform allows it, credentials belong in a secret manager, a store hardened specifically for that purpose, or are mounted as a file. Many container platforms, however, still pass them in as environment variables. In that case it matters all the more to keep permissions per service tight and to rotate credentials regularly.
The community around the project is discussing exactly this. An open draft proposes a new factor called “Identity”: the application should authenticate to every connected service with its own short-lived credentials. The environment variable then no longer holds the secret itself, only the location of the currently valid credentials. As of October 10, 2026, the draft has not been adopted.
Logs: without metrics and traces, the picture is incomplete
Factor XI treats logs as an event stream. Once a system consists of several services, that is not enough: you also need metrics (figures such as response times or error rates) and traces, which follow a request’s path through several services. Together, this is called observability: the ability to understand what is happening in your system.
The vendor-neutral standard for this is OpenTelemetry, and an open community proposal would extend the factor in this direction. Two gaps remain in the original. First, logs used for audits need tamper protection and retention rules. Second, logs often contain personal data such as IP addresses, which under the GDPR are subject to storage limitation and access control.
Scope: web applications, not every kind of software
The methodology was written for web applications and services running on servers. For a mobile app, such as the ones we build with React Native, it applies only to the backend behind it, the server side. With serverless functions, factor VII does not apply: the platform calls such pieces of code directly when needed. Databases and search indexes need patterns of their own for their state.
Sign-in, permissions and access control have no factor of their own in the original. We close that gap with Keycloak, open-source software for sign-in and permissions: multi-factor authentication, single sign-on and roles are standard in our projects. Single sign-on means one login for several applications.
Existing software: step by step instead of all at once
Converting existing software takes effort, and for a small internal application not every factor pays off. For software modernization, we start with an assessment and then replace the old system module by module while it keeps running. To be honest: not every legacy system should be modernized. Sometimes our recommendation is to keep running it and harden it.
In short: we stick to the principles of 2011, not to their examples.
Next steps
To finish, three questions you can use to check your existing software or a new quote:
- Is the repository in your name, and can every running version be traced back to a specific point in its change history?
- Are the credentials stored outside the code, and can they be swapped without a new build?
- Is the rollback to the previous version documented and rehearsed?
If any answer is “I don’t know,” you have found your starting point. For a quote, one more rule applies: what is not in it usually does not get delivered either. You will find more checks in the eleven questions for your quote that I put together for anyone commissioning software. You can see what a project with us costs, from the first version to ongoing operations, on our custom software development page.
If you want to review your application or your plans with us, let’s look at them together in a free, no-obligation call. We go through the twelve factors based on your answers and assess where the biggest risk lies. That gives you the first step, whether you take it with us or without us. You can book a slot directly in my calendar: Book an initial call.
