feedback from jake, will, and imbriaco

This commit is contained in:
Adam Wiggins
2011-10-20 17:38:05 -06:00
parent 6e618209ce
commit 34a2e3c2d3
5 changed files with 7 additions and 7 deletions
+1 -1
View File
@@ -5,5 +5,5 @@ The contributors to this document have been directly involved in the development
This document synthesizes all of our experience and observations on a wide variety of software-as-a-service apps in the wild. It is a triangulation on ideal practices app development, paying particular attention to the dynamics of the organic growth of an app over time, the dynamics of collaboration between developers working on the app's codebase, and [avoiding the cost of software erosion](http://blog.heroku.com/archives/2011/6/28/the_new_heroku_4_erosion_resistance_explicit_contracts/).
Our motivation is to raise awareness of some systemic problems we've 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. The format is inspired by Martin Fowler's books *[Patterns of Enterprise Application Architecture](http://books.google.com/books/about/Patterns_of_enterprise_application_archi.html?id=FyWZt5DdvFkC)* and *[Refactoring](http://books.google.com/books/about/Refactoring.html?id=1MsETFPD3I0C)*.
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. The format is inspired by Martin Fowler's books *[Patterns of Enterprise Application Architecture](http://books.google.com/books/about/Patterns_of_enterprise_application_archi.html?id=FyWZt5DdvFkC)* and *[Refactoring](http://books.google.com/books/about/Refactoring.html?id=1MsETFPD3I0C)*.
+1 -1
View File
@@ -5,7 +5,7 @@ A *backing service* is any service the app consumes over the network as part of
Backing services like the database are traditionally managed by the same systems admintrators as the app's runtime deploy. In addition to these locally-managed services, the app may also have services provided and managed by third parties. Examples include SMTP services (such as [Postmark](http://postmarkapp.com/)), metrics-gathering services (such as [New Relic](http://newrelic.com/) or [Loggly](http://www.loggly.com/)), binary asset services (such as [Amazon S3](http://aws.amazon.com/s3/)), and even API-accessible consumer services (such as [Twitter](http://dev.twitter.com/), [Google Maps](http://code.google.com/apis/maps/index.html), or [Last.fm](http://www.last.fm/api)).
**The code for a twelve-factor app makes no distinction between local and third party services.** To the app, both are backing services, accessed via a URL or other locator/credentials stored in the [config](/config). A [deploy](/codebase) of the twelve-factor app should be able to swap out a local MySQL database with one managed by a third party (such as [Amazon RDS](http://aws.amazon.com/rds/)) without any changes to the app's code. Likewise, or a local SMTP server could be swapped with a third-party SMTP service (such as Postmark) without code changes. In both cases, only the resource handle in the config needs to change.
**The code for a twelve-factor app makes no distinction between local and third party services.** To the app, both are backing services, accessed via a URL or other locator/credentials stored in the [config](/config). A [deploy](/codebase) of the twelve-factor app should be able to swap out a local MySQL database with one managed by a third party (such as [Amazon RDS](http://aws.amazon.com/rds/)) without any changes to the app's code. Similarly, a local SMTP server could be swapped with a third-party SMTP service (such as Postmark) without code changes. In both cases, only the resource handle in the config needs to change.
Each distinct backing service is a *resource*. For example, a MySQL database is a resource; two MySQL databases (used for sharding at the application layer) qualify as two distinct resources. The twelve-factor app treats these databases as *attached resources*, which indicates their loose coupling to the deploy they are attached to.
+2 -2
View File
@@ -7,13 +7,13 @@ An app's *config* is everything that is likely to vary between [deploys](/codeba
* Credentials to external services such as Amazon S3 or Twitter
* Per-deploy values such as the canonical hostname for the deploy
Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires **strict separatation of config from code**. Config varies substantially across deploys, code does not. A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could open sourced as-is without compromising any credentials.
Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires **strict separatation of config from code**. Config varies substantially across deploys, code does not. A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be open sourced as-is without compromising any credentials.
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.
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 an combinatorial explosion of config which makes managing deploys of the app very brittle.
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.
In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as "environments," but instead are independently controllable for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.
+2 -2
View File
@@ -1,7 +1,7 @@
## X. Dev/prod parity
### Keep development and production as similar as possible
### Keep development, staging, and production as similar as possible
Historically, there is a substantial gap between development (a developer making live edits to a local [deploy](/codebase) of the app) and production (a running deploy of the app accessed by end users). Gaps manifest in three areas:
Historically, there is a substantial gap between development (a developer making live edits to a local [deploy](/codebase) of the app), staging (a near-clone of the production deploy for doing dry runs of new releases), and production (a running deploy of the app accessed by end users). Gaps manifest in three areas:
* **The time gap:** A developer may work on code that takes days, weeks, or even months to go into production.
* **The personnel gap**: Developers write code, ops engineers deploy it.
+1 -1
View File
@@ -29,7 +29,7 @@ The Twelve Factors
### Fast startup and graceful shutdown maximize robustness
## [X. Dev/prod parity](/dev-prod-parity)
### Keep development and production as similar as possible
### Keep development, staging, and production as similar as possible
## [XI. Logs](/logs)
### Logs are event streams