Future-proof systems#

Preparation#

Read the following:

Introduction#

Future-proof system

system that is designed to remain functional, adaptable, and maintainable over time. Change of new hardware and maintaining personal should not significantly affect its operation.

Exercise 8

Look at Designing a future-proof health monitoring system. Which guidelines would you have for this system?

Exercise 9

Do you think mainframe computers are future-proof? Why?

https://upload.wikimedia.org/wikipedia/commons/4/45/IBM_z13_and_LinuxONE_Rockhopper.jpg

Fig. 5 A pair of IBM mainframes. On the left is the IBM z Systems z13. On the right is the IBM LinuxONE Rockhopper.
CC BY-SA 4.0. By Agiorgio. Source: Wikimedia Commons
#

The twelve factors#

Twelve-Factor App methodology

a methodology for building software-as-a-service applications with portability and resilience in mind.

Following comments based on Twelve Factor commit fcb9858

Codebase#

codebase

any single repository, or any set of repositories that share a root commit.

https://github.com/twelve-factor/twelve-factor/raw/next/images/codebase-deploys.png

Fig. 6 One codebase can be deployed in multiple environments#

  • one codebase corresponds to a single app.

  • two apps require two codebases

    • here we have a distributed system

Exercise 10

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Dependencies#

  • app declares all dependencies, which results in a deterministic environment, e.g.,

    • Python pip install

    • Ruby bundle install using Gemfile

  • app does not rely on implicit existence of system-wide packages. Dependencies are isolated if possible, e.g.,

    • Python virtualenv

  • app does not rely on the implicit existence of any tools, e.g.,

    • ImageMagick or curl should be vendored into the app

Exercise 11

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Config#

config

everything that is likely to vary between deploys

  1. separation

    • strict separation of config from code

    • different deployments differ in their configuration

  2. environment variables are better than config.yml, because

    • files can be accidentally committed to the repository

    • files can be scattered in different places

    • environment variables are language- or framework-agnostic

  3. treat environment variables as granular controls, never group them by environment, i.e., instead of a single config.js that contains all the environments, reference environment variables in config.js.

Exercise 12

Imagine a software-as-a-service application that serves multiple customers. Each gets a dedicated instance of the app, and each instance is deployed separately.

Does the following approach follow the config guideline of the twelve-factors methodology? If not, improve it. If yes, explain.

environments:
  staging:
    DATABASE_URL: postgres://staging-db-url
    API_KEY: staging-api-key
  production:
    DATABASE_URL: postgres://prod-db-url
    API_KEY: prod-api-key

Backing services#

backing service

any service the app consumes over the network as part of its normal operation

e.g., PostgreSQL, RabbitMQ, Dovecot, Memcached, OpenStreetMap etc

  1. each backing service is treated as an attachable resource.

    https://github.com/twelve-factor/twelve-factor/raw/next/images/attached-resources.png

    Fig. 7 Backend services are attached using URLs. This makes their replacement convenient.#

  2. Every service can be used as an URL. From the perspective of the deployment, there is no distinction between a self- and externally-managed backend service.

Exercise 13

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Build, release, run#

  1. Distinct stages

    • build: transforms into an executable bundle using the dependencies

    • release: deploys the executable using the config

    • run: runs the app in the execution environment

  2. each release is a unique, immutable snapshot that can be referenced

  3. keep run minimal, push complexity to the build

Exercise 14

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Processes#

  1. app is executed as one or more processes.

  2. app’s processes are stateless and share nothing. This enables convenient horizontal scaling. Each request can be served by any node. The sessions can be stored in Memcached or Redis.

Exercise 15

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Port binding#

  1. an app is completely self-contained, instead of being a module of another service. Example: a PHP app must be started by Nginx. Solution: integrate a web server in your app, e.g., Tornado in Python

  2. Use port binding to route requests to your app. Example your app runs on localhost:5000 which you use for development. In deployment, the webserver routes the requests to this port.

Exercise 16

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Concurrency#

  1. an app is executed as one or more processes, e.g., PHP as child processes of the webserver started by demand, Java executes a single process, but starts individual threads

  2. apps use unix process model. If the app needs many processes, then all the processes are started using a single point.

  3. Separate different workload types to different processes for scaling

  4. Execution environment manages processes, e.g., systemd, foreman (during development)

https://github.com/twelve-factor/twelve-factor/raw/next/images/process-types.png

Fig. 8 An app divided into three different process types. This allows scaling dependent on the workload type#

Exercise 17

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Disposability#

  1. Processes can be started or stopped easily without impacting the whole applications

    • e.g., a web server process can be replaced on demand without disrupting the system after an update

  2. Minimize start-up time

    • minimizes down-time after an update or failover

  3. Graceful shutdown

    Web process:

    1. cease to listen on the service port, or send a maintenance message

    2. allow current requests to finish

    Worker process:

    1. Return the current job to the work queue, e.g., in RabbitMQ

  4. Tolerance against sudden termination, e.g., hardware failure

    • e.g., return the requests to the queue and retry, if the service times out

Exercise 18

  • Does this factor make the system future-proof?

  • If yes, give a counter example which shows that the system is not future-proof if this factor is not taken into account.

Development/production parity#

minimize the gaps between development, staging and production. Gap examples

  • time gap: developer’s work takes a long time and is not deployed

  • personnel gap: developers are not involved in deployment (but ops engineers)

  • tools gap: developers use local tools, e.g., SQLite instead of PostgreSQL.

Solutions:

  • use CI/CD

  • use the same tools as in the production

Logs#

  1. app produces logs as a stream of time-ordered events, e.g.,

    • text format

    • one event per line typically

    • exceptions may span over many lines

    • unbuffered

    • use stdout or stderr

  2. app is not responsible for routing or storage of logs.

    • use Splunk for log indexing and analysis

    • Hadoop/Hive as a general-purpose data warehousing system

    • these tools can implement anomaly detection

Admin processes#

  1. administrative task processes are separate from business logic processes

  2. admin processes are part of the same environment, i.e., use the config file

Example:

  • bundle exec thin start for a web process

  • bundle exec rake db:migrate for an administration task

Criticism#

Note that the criticism may be directed on a previous version of the methodology. We covered the live version.

Further resources#