3.2 KiB
IV. Backing Services
Treat backing services as attached resources
A backing service is any service the app accesses over the network as part of its normal operation. Examples include datastores (such as MySQL or CouchDB), messaging/queueing systems (such as RabbitMQ or Beanstalkd), SMTP services for outbound email (such as Postfix), and caching systems (such as Memcached).
Traditionally, backing services such as the database are considered "local," and part of the app. 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), metrics-gathering services (such as New Relic or Loggly), binary asset services (such as Amazon S3), and even API-accessible consumer services (such as Twitter, Google Maps, or Last.fm).
The twelve-factor app makes no distinction between local versus third party services. To the app, both are backing services, accessed via a URL or other locator/credentials stored in the config. A deploy 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) 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.
A backing service like Amazon RDS provisions into private resources. The app has a resource handle (ideally in URL form, like mysql://user:pass@host/db) which points to the private resource and provides everything the app needs to access it. For a service Amazon RDS, the resource is a database. For a service like New Relic or a consumer service like Last.fm, the resource is an account or a user.
Further, the resources are referred to as attached resources to indicate their loose coupling to the deploy they are connected to. Resources can be attached to and detached from deploys at will.
For example, the process of upgrading a database to a server with more compute and memory will typically look like this:
- Provision a new, larger database resource from the database service provider.
- Put the app into maintenance mode.
- Take a backup of the existing database.
- Load the backup into the newly provisioned database.
- Detach the existing database, by clearing the env var which contains its handle (e.g.,
MYSQL_URLorDATABASE_URL). - Attach the new database, by setting that same env var with the resource handle for the new resource.
- Take the app out of maintenance mode.
A prudent administrator will keep the previous database around, unattached to any app deploy, for a few days while the new database is confirmed to be operating correctly. Then the unattached database can be deprovisioned.