When I read factor V of the Twelve-Factor App I see only one clear and obvious end result being described:

it is impossible to make changes to the code at runtime

Perhaps it is supposed to be obvious, but as I'm writing an internal document for my coworkers why we should observe more best practices (like the Twelve-Factor App) I realized I can't put my finger on exactly what separating build, release and run is supposed to do.

Is it supposed to enable better isolated testing of individual steps? (If I have a build, I can unit test it and validate the dependency declarations. If I have a release perhaps I can validate the configuration, but I can't validate/integration test without a full running deploy.)

If we did a good job at the eleven other factors in the Twelve Factor App, but did build, release, and run haphazardly or not at all, what would we be missing?

  • 1
    beware the cargo-cult! Best practices do not necessarily mean best practice for your specific situation. – gbjbaanb Mar 8 '16 at 11:57
  • Great question. I'm certain many people miss the "release" part of this advice. Ewan provides great examples. – Andriy Drozdyuk Jun 21 '18 at 4:55

I think this is probably best described by stating the bad practices it would seem to be trying to avoid. I can remember the old days when these were common practice. But with modern 'dev ops' tools being so easy to use these days I doubt they are seen anymore.

Live code fixes. (Run and Build stages are joined) A bug is reported, I fix it on my dev machine, build locally and ftp the new dll/exe onto the live box. Copying it right over the top of the existing one. No check in to source control. My dev box is the only place the code is stored, if another dev does the same with another bug, the first bug is reintroduced. No roll back is possible

Live config changes. (Run and Release stages are joined) I go on a live box and change the config manually with notepad/vi and restart the app and it picks up the new settings. Again no central storage of the config, no backing up the old config, no documentation. If the box goes down the changes are lost, if I have multiple nodes they all end up with different configs.

No central build. (Build stage is ill defined) Although source control is used, the build is done locally from whatever version happens to be on that box at the time. Although the release is static, you cant tie it back to a definite version of the code. Local differences, such as what libraries are installed and global settings, like paths and the registry all effect the final release. So what works this time, might not work next time.

One more related to no central build

No storage of releases. (Release stage is ill defined) The build is done and deployed to live. But the binaries are not versioned and stored. The question of 'what version is live' is difficult to answer and rollbacks/re-deployments rely on backups of the live machines rather than deploying 'from scratch'


I think what you're asking is explained (though not very clearly) in the link you posted. The most relevant bit:

The twelve-factor app uses strict separation between the build, release, and run stages. For example, it is impossible to make changes to the code at runtime, since there is no way to propagate those changes back to the build stage.

If you make changes to the deployed app, you make your life more difficult. Your build is no longer reproducible (since it has post-build steps done at runtime, and which are tracked nowhere). You may lose patches and changes, since they aren't tracked anywhere. If you want to deploy to another server, you must manually copy every change you made to the first server.

In the best scenario, you are forced to manually copy every change you make on production back to your source build, which is very error-prone.

  • Our code requires us to create some empty directories, to create a particular file and symlink some modules together after initial drop. Salt makes it reproducible, but there's no sane way to copy it back into the main repository, and I think our Salt opscode is wrapping or hiding architectural problems in the application(s). Strictly speaking, though, are we actually violating this "factor"? Maybe you can make anything a 12 factor app with enough opscode, but OTOH everyone has to use some kind of opscode and deployment tools. I guess the value of this factor is "less" opscode? – kojiro Mar 7 '16 at 20:02
  • I don't know if the scenario you describe counts as "modifying code at runtime". It does make your installation more brittle if the steps you describe aren't automated, but I assume you're saying they are. If they are automated and reproducible, I don't see any problem. – Andres F. Mar 7 '16 at 20:12
  • 1
    @kojiro Would it be possible to make "the code" the file(s) and symlink(s) if they don't exist? Once that's in place, you can then ensure that in integration tests. – Vatine Mar 8 '16 at 11:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.