"A methodology for building software-as-a-service applications"
The Heroku Team
"Our motivation is to raise awareness of some systemic problems we’ve seen in modern application development, to provide a shared vocabulary for discussing those problems, and to offer a set of broad conceptual solutions to those problems with accompanying terminology."
One codebase, tracked in revision control, many deploys
Explicitly declare and isolate dependencies.
Store config in the environment
If your codebase was made open source, would you expose credentials?
Treat backing services as attached resources
Your code shouldn't know the difference if you changed out a local redis instance with one served by AWS through Elisticache.
Strictly separate build and run stages.
The build stage is managed by devs and it does all the heavy lifting. The run stage should be simple and bullet-proof so if an app has to restart, it shouldn't need any human intervention.
Execute the app as one or more stateless processes
Data should be stored in a database or persistent key-value store like redis so if one server goes down in the middle of a users session, another server can handle the traffic and the app is none the wiser.
Export services via port binding
Example: You have an API that serves external customers (untrusted) as well as your web app (trusted). You might set up a separate url that your web app uses that bypasses firewall and authentication so it's a bit faster.
Scale out via the process model
Have lots of little processes handling individual tasks.
Ex: 1 process handles http traffic,
1 process handles websockets,
1 process handles sending welcome emails, etc...
"In the 12 factor app, processes are a first-class citizen."
Maximize robustness with fast startup and graceful shutdown.
If your app crashes, it should be able to start back up quickly and cleanly.
Beyond loading code, your app should have everything it needs waiting in high speed databases or caches so it can start up snappily and be ready to serve requests.
Keep development, staging and production as similar as possible.
It's more desirable to be able to develop and deploy changes quickly. In order to facilitate this, it's best to make a developer's local environment as close to production as possible.
I.E. - using the same backing services, the same configuration management techniques, the same versions of software libraries, etc...
Treat logs as event streams.
In the ideal situation, the logs should be captured as a stream of events and pushed into a real time consolidated system for long-term archival and data-mining.
At the very least, you should be capturing errors and sending them to an error reporting service like New Relic or Air Brake.
Run admin/management tasks as one-off processes.
One-off tasks like cleaning up data, running analytics for a presentation, turning on and off features for A/B testing should be run in an identical environment as production.
Don't run updates directly against a database or from a local terminal window.