12-Factor App
A Methodology for Building
SaaS Apps
MM Meetup, September 2015, Ankara
/Abdullah Cetin CAVDAR @accavdar
Me :)
Software Engineer
Continuous Reader / Learner
Runner / Rider
Snooker Lover
Headbanger m/
@udemy
12factor.net
What's 12-Factor
App?
It's a methodology for building
SaaS apps
Why do we care?
Tries to define the systematic
problems in app development
Tries to offer a set of broad
conceptual solutions to those
problems
What are the
properties of an
app?
Uses declarative format for
setup automation
to minimize time and cost for new developers joining the project
Has a clean contract with the
underlying operating system
offering maximum portability between execution environments
Is suitable for deployment on
modern cloud platforms
no need for servers and systems administration
Minimizes divergence between
development and production
enabling continuous deployment for maximum agility
Can scale up
without significant changes to tooling, architecture, or
development practices
The 12-Factors
1. Codebase
One codebase tracked in revision control,
many deploys
codebase == code repo == repo
tracked in a version control
system:  ,  ,   etc.git mercurial svn
one repo, many deploys
app != many repos
many repos = distributed system
2. Dependencies
Explicitly declare and isolate dependencies
PS: Think about new developers :)
Never rely on implicit existence of packages
Dependency Declaration
Declare all dependencies, completely and
exactly, via a dependency declaration
manifest
Dependency Isolation
Ensure that no implicit dependencies "leak
in" from the surrounding system
pip
virtualenv
source ~/udemy-py3-env/bin/activate &&
pip install -r requirements/dev.txt
Do not rely on the implicit
existence of any system tools
Bundle them with your app
3. Config
Store config in the environment
What's config?
Everything that is likely to vary
between deploys
Resource Handles (db, memcache, backing services, ...)
Credentials to external services (twitter, AWS, ...)
Per-deploy values (canonical hostname, ...)
PS: It does not include internal app config (config/routes.rb, bean
config, ...)
Can you make
your repo open
source?
Store config in Environment
Variables
Keep your config outside the app
Env vars are easy to change between deploys
No secret in version control
You may use Environments
but 12-Factor App recommends Env Vars
dev
test
staging
prod
...
It's also called Profiles
4. Backing Services
Treat backing services as attached resources
A backing service is any service
the app consumes over the
network
Data Store (MySQL, MongoDB, AWS S3...)
Messaging/Queueing Systems (RabbitMQ, Kafka, ...)
Caching Systems (Redis, Memcached, ...)
SMTP Services (Postfix, ...)
No distinction between local
and third party services
They are Attached Resources
accessed via a URL or other
locator/credentials stored in the config
They are loosely coupled with the deployed app
They are easily swap out without any changes to the app’s code
Microservices?
5. Build, Release,
Run
Strictly separate build and run stages
A codebase is transformed into
a deploy through three stages
Build
Release
Run
Build
Converts a code repo into an
executable bundle
Build = Dependencies + Binaries + Assets
Release
Get the build and combine it
with the current config
Release = Build + Config
Run
Run the app in the execution
environment
Run = Run process against release
Strict separation between the
build, release, and run stages
For example, it is impossible to make
changes to the code at runtime
Use tools to easily rollback to previous release
Version your releases with unique release ids (ex: v101)
Any change must create a new release
6. Processes
Execute the app as one or more stateless
processes
Processes are stateless and
share-nothing
Any data that needs to persist must be
stored in a stateful backing service
Never assume that anything cached in memory or on disk will be
available on a future request or job
Never use or rely on sticky sessions, use a data store that offers time-
expiration, such as Memcached or Redis
7. Port Binding
Export services via port binding
App is completely self-contained
The web app exports HTTP as a service by binding to a port
Use dependency declaration to
add a web server library
Tornado for Python
Thin for Ruby
Jetty or Tomcat for Java
Use it not only for HTTP
Any kind of service runs via a process binding to a port, i.e Redis
Port-binding approach means that one app can become the backing
service for another app
8. Concurrency
Scale out via the process model
Processes are a first class citizen
Developers can architect their app to handle diverse workloads by
assigning each type of work to a process type
HTTP requests may be handled by a web process
Long-running background tasks handled by a worker process
...
Each process can handle its own multiplexing
Threads in runtime VM (Java, ...)
Async/Event model (Twisted, node.js, ...)
Use system process managers (i.e Upstart) to
Manage process
Respond to crash process
Handle user initiated restarts and shutdowns
Scale Out?
with share-nothing, horizontally partitionable nature of app processes
Simple and Reliable Concurrency
9. Disposability
Maximize robustness with fast startup and
graceful shutdown
Processes are disposable
meaning they can be started or stopped at
a moment’s notice
fast elastic scaling
rapid deployment of code and config changes
robustness of production deploys
Minimize startup time
more agility for the release process and scaling up
aids robustness
Shut down gracefully when
they receive a SIGTERM
Cease to listen on the service port, allow any current requests to
finish, and then exit (Web Process)
Return the current job to the work queue (Worker Process)
Try to make all jobs reentrant or
Make the operation idempotent
Be robust against sudden death
Use a robust queueing backend
RabbitMQ
Beanstalkd
Redis
10. Dev/Prod
Parity
Keep development, staging, and
production as similar as possible
Development vs Production
Gaps
Time Gap
A developer may work on code that takes
days, weeks, or even months to go into
production
Personnel Gap
Developers write code, ops engineers
deploy it
Tools Gap
Stack like Nginx, SQLite, and OS X in dev,
Apache, MySQL, and Linux in prod
Design for continuous
deployment
Keep the gap between development and
production small
Make the time gap small
A developer may write code and have it
deployed hours or even just minutes later
Make the personnel gap small
Developers who wrote code are closely
involved in deploying it and watching its
behavior in production
Make the tools gap small
Keep development and production as
similar as possible
Resist to use different backing services between development and
production
Chef, Puppet, ...
Docker, Vagrant, ...
11. Logs
Treat logs as event streams
Never concern itself with
routing or storage of its output
stream
Each running process writes its event
stream, unbuffered, to stdout
Index and analyse (splunk,
hive/hadoop, ...) your event
streams to
Finding specific events in the past
Large-scale graphing of trends (such as requests per minute)
Active alerting according to user-defined heuristics
12. Admin Processes
Run admin/management tasks as one-off
processes
One-off administrative or
maintenance tasks for the app
Running DB migrations
Running a console (REPL shell)
Running one time script
Run them in an identical environment as the regular app
Ship with application code to avoid synchronization issues
Favor languages which provide a REPL shell out of the box
Also check:
Microservices
Reactive Manifesto
Containerization ( ,  ,
)
LXC Docker
CoreOS
Thank you :)
Questions?
THE END
by Abdullah Cetin CAVDAR / @accavdar

12-Factor App