mirror of
https://github.com/kennethreitz/12factor.git
synced 2026-06-05 23:10:17 +00:00
feedback from jake and hagelberg
This commit is contained in:
@@ -11,7 +11,7 @@ A [codebase](/codebase) is transformed into a (non-development) deploy through t
|
||||
|
||||

|
||||
|
||||
A *release* is a combination of a build (the executable bundle generated in the build stage) and a [config](/config), a set of environment variables to determine runtime behavior.
|
||||
A *release* is a combination of a build (the executable bundle generated in the build stage) and a [config](/config) (the set of environment variables which determine runtime behavior).
|
||||
|
||||
New builds always trigger new releases (since the build has been updated). Config changes also trigger a new release (since the config has been updated). A release requires restarting all running processes in order to bring all processes onto the new release.
|
||||
|
||||
|
||||
@@ -9,6 +9,6 @@ Any computer program, once run, is represented by one or more processes. Web ap
|
||||
|
||||
This does not exclude individual processes from handling their own internal multiplexing, via threads inside the runtime VM, or the async/evented model found in tools such as [EventMachine](http://rubyeventmachine.com/), [Twisted](http://twistedmatrix.com/trac/), or [Node.js](http://nodejs.org/). But an individual VM can only grow so large (vertical scale), so the application must also be able to span multiple processes running on multiple physical machines.
|
||||
|
||||
The process model truly shines when it comes time to scale out. The [share-nothing, horizontally partitionable nature of twelve-factor app processes](/processes) means that adding more concurrency is a simple and reliable operation. The array of process types and number of processes of each type is known as the *process formation*:
|
||||
The process model truly shines when it comes time to scale out. The [share-nothing, horizontally partitionable nature of twelve-factor app processes](/processes) means that adding more concurrency is a simple and reliable operation. The array of process types and number of processes of each type is known as the *process formation*.
|
||||
|
||||
Twelve-factor app proceses [should never daemonize](http://dustin.github.com/2010/02/28/running-processes.html) or write PID files. It counts on the operating system's process manager (such as [Upstart](http://upstart.ubuntu.com/), a distributed process manager on a cloud platform, or a tool like [Foreman](http://blog.daviddollar.org/2011/05/06/introducing-foreman.html) in development) to manage [output streams](/logs), respond to crashed processes, and handle user-initiated restarts and shutdowns.
|
||||
Twelve-factor app processes [should never daemonize](http://dustin.github.com/2010/02/28/running-processes.html) or write PID files. Instead, rely on the operating system's process manager (such as [Upstart](http://upstart.ubuntu.com/), a distributed process manager on a cloud platform, or a tool like [Foreman](http://blog.daviddollar.org/2011/05/06/introducing-foreman.html) in development) to manage [output streams](/logs), respond to crashed processes, and handle user-initiated restarts and shutdowns.
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ Apps sometimes store config as constants in the code. This is a violation of tw
|
||||
|
||||
Another approach to config is the use of config files which are not checked into revision control, such as `config/database.yml` in Rails. This is a huge improvement over using constants which are checked into the code repo, but still has weaknesses: it's easy to mistakenly check in a config file to the repo; there is a tendency for config files to be scattered about in different places and different formats, making it hard to see and manage all the config in one place. Further, these formats tend to be language- or framework-specific.
|
||||
|
||||
**The twelve-factor app stores config in *environment variables*** (often shortened to *env vars* or *env*). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java Sytem Properities, they are a language-agnostic Unix standard.
|
||||
**The twelve-factor app stores config in *environment variables*** (often shortened to *env vars* or *env*). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java system properties, they are a language-agnostic Unix standard.
|
||||
|
||||
Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called "environments") named after specific deploys, such as the `development`, `test`, and `production` environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as `staging` or `qa`. As the project grows further, developers may add their own special environments like `joes-staging`, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle.
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ Summarizing the above into a table:
|
||||
|
||||
Developers sometimes find great appeal in using a lightweight backing service in their local environments, while a more serious and robust backing service will be used in production. For example, using SQLite locally and PostgreSQL in production; or local process memory for caching in development and Memcached in production.
|
||||
|
||||
**The twelve-factor developer resists the urge to use different backing services between development and production**, even when adapters theoretically abstract away any differences in backing services. Differences between backing services mean that tiny incompatibilities crop up, causing code that worked and passed tests in development or staging to fail in production. These types of errors create friction that disincentives continuous deployment. The cost of this friction and the subsequent dampening of continuous deployment is extremely high when considered in aggregate over the lifetime of an application.
|
||||
**The twelve-factor developer resists the urge to use different backing services between development and production**, even when adapters theoretically abstract away any differences in backing services. Differences between backing services mean that tiny incompatibilities crop up, causing code that worked and passed tests in development or staging to fail in production. These types of errors create friction that disincentivizes continuous deployment. The cost of this friction and the subsequent dampening of continuous deployment is extremely high when considered in aggregate over the lifetime of an application.
|
||||
|
||||
Lightweight local services are less compelling than they once were. Modern backing services such as Memcached, PostgreSQL, and RabbitMQ are not difficult to install and run thanks to modern packaging systems, such as [Homebrew](http://mxcl.github.com/homebrew/) and [apt-get](https://help.ubuntu.com/community/AptGet/Howto). The cost of installing and using these is low compared to the benefit of dev/prod parity and continuous deployment.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## IX. Disposability
|
||||
### Fast startup and graceful shutdown maximize robustness
|
||||
|
||||
The twelve-factor app's [processes](/processes) are *disposable*, meaning they can be started or stopped a moment's notice. This facilitates fast elastic scaling, rapid deployment of [code](/codebase) or [config](/config) changes, and robustness of production deploys.
|
||||
The twelve-factor app's [processes](/processes) are *disposable*, meaning they can be started or stopped at a moment's notice. This facilitates fast elastic scaling, rapid deployment of [code](/codebase) or [config](/config) changes, and robustness of production deploys.
|
||||
|
||||
Processes should strive to minimize startup time. Ideally, a process takes a few seconds from the time the launch command is executed until the process is up and ready to receive requests or jobs. Small startup time provides more agility for the [release](/build-release-run) process and scaling up; and it aids robustness, because the process manager can more easily move processes to new physical machines when warranted.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ In the simplest case, the code is a stand-alone script, the execution environmen
|
||||
|
||||
**Twelve-factor processes are stateless and [share-nothing](http://en.wikipedia.org/wiki/Shared_nothing_architecture).** The filesystem sitting beneath the process is either read-only (attempting a write will produce an error), or completely ephemeral (when the process terminates, all state written to disk will be discarded). Any data that needs to persist must be stored in a stateful [backing service](/backing-services), typically a database.
|
||||
|
||||
Process memory space or an ephemeral filesystem can potentially be used as a brief, single-transaction cache. For example, downloading a large file, operating on it, and storing the results of the operation in the database. The twelve-factor app never assumes that anything cached in memory or on disk will be available on a future request or job -- with many processes of each type running, chances are high that that a future request will be served by a different process. Even when running only one process, a restart (triggered by code deploy, config change, or the execution environment relocating the process to a different physical location) will wipe all filesystem and in-memory state.
|
||||
Process memory space or an ephemeral filesystem can potentially be used as a brief, single-transaction cache. For example, downloading a large file, operating on it, and storing the results of the operation in the database. The twelve-factor app never assumes that anything cached in memory or on disk will be available on a future request or job -- with many processes of each type running, chances are high that a future request will be served by a different process. Even when running only one process, a restart (triggered by code deploy, config change, or the execution environment relocating the process to a different physical location) will wipe all filesystem and in-memory state.
|
||||
|
||||
Asset packagers (such as [Jammit](http://documentcloud.github.com/jammit/) or [django-assetpackager](http://code.google.com/p/django-assetpackager/)) use the filesystem as a cache for compiled assets. A twelve-factor app prefers to do this compiling during the [build stage](/build-release-run), such as the [Rails asset pipeline](http://ryanbigg.com/guides/asset_pipeline.html), rather than at runtime.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user