Notes on ‘The Twelve-Factor App’ for WordPress


In an effort to improve my DevOps skills, I’m working to understand how to develop and deploy WordPress sites as a ’12 Factor Application.’

I am reading through ‘The Twelve Factor App’ as part of thoroughly understanding the Roots/Bedrock platform. I am adding my notes here.

Additionally the Roots team wrote their own notes on ‘The Twelve Factor App’ as it applies to WordPress.


‘The Twelve Factor App’ is a set of principles that a modern project must adhere to.

It establishes rules and guidelines as a set of best practices in an effort to prevent bad things from happening.

1. Codebase

  • An ‘app’ has one and only one codebase
  • Apps with shared code should have them stored as dependent libraries
  • A codebase can be deployed many times, in different environment instances (production, staging, development)
  • There may be several versions of the same app codebase in different environments.
  • There should be a naming convention to differentiate versions within the Codebase repo
  • WordPress:

2. Dependencies

  • External dependencies must be explicitly declared and managed by the app
    • The app has a dependency declaration manifest
    • The app has a dependency isolation tool to execute the dependencies
    • No other external libraries should ‘leak’ in.
    • Every app environment should be ‘Exact and Exhaustive’ to say the least.
  • Don’t rely on implicit existence
    • For example, don’t assume a bash script or GNU/Linux binary (curl) will be present on the operating system
    • Everything required for the app to run must be explicitly declared.
  • Use a packaging system for linking external libraries
    • The third party code is not included in your repository
    • Ruby has the ‘gem’ system bundler as the isolation tool
    • For Ruby the dependency isolation command is ‘> bundle exec
  • New developers should be able to quickly use the build command to rebuilt the system locally.
    • For example on Ruby that build command is ‘> bundle install
  • Composer is the packaging system for PHP.
  • Packagist is the defacto package repository for PHP
  • WordPress: This is a new idea to WordPress. Plugins are external dependencies, but not explicitly declared in a manifest.
  • WordPress: The WordPress core directory should be a dependency to the entire app.
  • WordPress: WPackagist is the current de facto for WordPress packages
    • Not supported by WordPress project
    • It just mirrors the repos
  • WordPress: WordPress needs a lot of help and customization to set up the directory structure correctly.
    • (What are the things WordPress needs?) It’s covered in the link below, but what is the TLDR
  • WordPress: More reading on Composer
  • WordPress: Video on WordPress and Composer

3. Config

  • Different deployment environments will probably have different configurations
    • Especially for external 3rd party services
    • Configurations are things that are likely to change
    • Configurations are NOT things that are needed to configure the app, like the Rails ‘config/routes.rb’ file
  • Configurations should not be hardcoded in the code, they should be separate.
  • If the codebase could be open-sourced at any moment, without fear of critical keys being exposed to the public, then there is a correct separation of code and configuration.
  • Configs should be stored in environmental variables. These are Bash variables on Linux
  • WordPress: Some configs should stay in the wp-config.php file, but others should be set in the environment
  • WordPress: In the Bedrock set up, config variables are set up in the root .env file.

4. Backing Services

  • Databases and other stores are used as ‘attached resources’
  • No distinction between local and remote resources
    • Simply attached by URL
    • Loosely Coupled
  • Should be able to swap these resources with only config changes
  • Resources should not be hardcoded in the database
  • Application code should abstract their connections
  • Attach and Detach resources at will
  • WordPress: Mostly just concerns MySQL attachment
  • WordPress: Very easy, already set up with environmental variables

5. Build, Release, Run

  • A codebase is transformed into a deployment in three distinct stages:
    • Build: Fetch dependencies and compile binaries and assets
    • Release: Combine the build with the env config to create new instance in /releases subdirectory
    • Run:
  • Releases have a unique identifier, like a timestamp or version number
  • Releases can be stored in a /releases subdirectory, symlinked to the current runtime
  • The runtime can then be ‘rolledback’ to a previous release
  • WordPress: Build with ‘composer install’ and then compile assets
  • WordPress: Can use Capistrano easily for one button deploys

6. Processes

  • Apps are stateless processes, they should not share resources with other processes
  • Can’t assume that resources will be there
    • Sessions:
    • Uploads
  • (I’m a bit lost on all this)
  • WordPress: Uploads and Sessions
  • More Reading: Shared Nothing Architecture

7. Port Binding

  • An app’s service should run standalone and be tied to a port

8. Concurrency

  • Something Something Horizontal Scaling Something

9. Disposability

  • App processes should be able to be started and stopped at a moments notice
  • Processes should end gracefully when given SIGTERM
  • WordPress: Seems well managed by nginx and PHP-FPM

10. Dev/Prod Parity

  • Gaps appear between codebase versions; keep it as similar as possible
    • Time Gap
    • Personnel Gap
    • Tool Gap
  • The goal is Continuous Deployment
  • WordPress: User Vagrant

11. Logs

  • Logs are event streams
  • stoud
  • WordPress: WordPress doesn’t offer great logs
  • WordPress: nginx and php logs are not the same thing

12. Admin Processes

  • Run code admin processes as a one time process
  • For example, when upgrading the database using rake db:migrate
  • Admin code should ship with codebase
  • WordPress: Use wp-cli






Leave a Reply

Your email address will not be published. Required fields are marked *