- Methodology for building SaaS apps
. Good teams fail when you don’t have a good culture that embraces DevOps, microservices and not giant monoliths
Goals
- Minimize time and cost for new developers to join a project
- Platform-agnostic code for maximum portability (i.e. cloud)
- Minimize divergence between dev and prod code, enabling continuous deployment for maximum agility
- Minimize scale up cost
These best practices are based on a few specific parameters for deployment of cloud-native applications:
- It uses declarative formats for setup automation.
- It works with a clean contract with the operating system for greater portability between environments
- It limits the differences between development and production, for continuous deployment
- And it allows for scaling up and down without major changes
12 Factors
- Codebase: Single repository per app (e.g. GitHub), deployed on various machines (e.g. staging, prod).
- Dependencies: All dependencies are explicitly declared in a packaging system (e.g. Bundler, Chef) and isolated from the wider system when the app is run.
- Config: Variables (i.e. values that vary between deploys, credentials) stored as environment variables (no code change, can’t be checked in to repo, OS agnostic, cleaner, scalable).
- Backing Services: All external dependencies (e.g. database, SMTP) are treated as attached resources, able to be swapped out without any code changes
- Build, Release, Run: Strictly separated, versioned, immutable, one-way process from code repository to build (most moving parts, complied and ready for execution), to release (build combined with a config), to run (fewest moving parts, launch in environment).
- Processes: Executed code is stateless and shares nothing — all data is stored in a stateful backing service (e.g. database, S3) although temporary storage can be used (e.g. memory, disk), but never depended upon.
- Port Binding: App is completely self-contained and provides its own webserver as a dependency — the only responsibility of the environment is binding to a port to serve requests.
- Concurrency: More smaller first-class citizen processes assigned to different process types working independently (collectively referred to as the process formation) to maximise scalability
- Disposability: Processes should start quick, shut down gracefully, be robust against sudden termination (e.g. hardware failure), and can be started or stopped at a moment’s notice.
- Dev/Prod Parity: Deploy hourly (time gap), coders also deploy (personnel gap), dev and prod environments are as similar as possible (tool gap) — including backing services (i.e. no developer shortcuts such as lightweight database via adapter)
- Logs: All running processed write to stdout captured and collated by the environment (e.g. Fluent, Papertrail) for tailing, indexing, graphical representation or analysis.
- Admin: Scripts should be checked into the codebase and executed remotely on th