https://12factor.net/
# Lesson: The Twelve-Factor App Methodology
## Introduction
The Twelve-Factor App is a set of principles for building software-as-a-service applications that are robust, scalable, and easy to deploy. It was created by developers at Heroku, a cloud platform as a service (PaaS) that has been used to deploy hundreds of thousands of applications.
## Objectives
By the end of this lesson, you should be able to:
- Understand the twelve factors that make up the methodology.
- Apply these factors to improve the design and deployment of web applications using Flask (Python) and Node.js.
## The Twelve Factors
Here's a brief overview of each factor with specific examples for Flask and Node.js:
### I. Codebase
**One codebase tracked in revision control, many deploys**
- **Flask & Node.js**: Use Git for version control. Each microservice or component of your application should have its own repository if they are deployed independently.
### II. Dependencies
**Explicitly declare and isolate dependencies**
- **Flask**: Use a `requirements.txt` file or a Pipfile (when using pipenv) to declare dependencies.
- **Node.js**: Declare your dependencies in a `package.json` file.
### III. Config
**Store config in the environment**
- **Flask**: Use environment variables with `os.environ` or the `python-dotenv` package.
- **Node.js**: Use the `dotenv` package to load environment variables.
### IV. Backing services
**Treat backing services as attached resources**
- **Flask & Node.js**: Use environment variables to store URLs and credentials for backing services like databases, and treat them as attached resources that can be replaced without code changes.
### V. Build, release, run
**Strictly separate build and run stages**
- **Flask & Node.js**: Use Docker containers to package your application and its dependencies. Use continuous integration and continuous deployment (CI/CD) pipelines to automate the build and release process.
### VI. Processes
**Execute the app as one or more stateless processes**
- **Flask & Node.js**: Ensure that any data that needs to persist is stored in a stateful backing service like a database, not in the process's memory.
### VII. Port binding
**Export services via port binding**
- **Flask**: Use Gunicorn or another WSGI server to bind to a port provided by the environment.
- **Node.js**: Bind to a port provided by the environment using `process.env.PORT`.
### VIII. Concurrency
**Scale out via the process model**
- **Flask & Node.js**: Use a process manager like Gunicorn (for Flask) or PM2 (for Node.js) to run multiple instances of your application.
### IX. Disposability
**Maximize robustness with fast startup and graceful shutdown**
- **Flask & Node.js**: Ensure that your application can start quickly and that it can shut down gracefully by handling SIGTERM signals.
### X. Dev/prod parity
**Keep development, staging, and production as similar as possible**
- **Flask & Node.js**: Use Docker to maintain consistency across environments. Use environment variables to manage any differences.
### XI. Logs
**Treat logs as event streams**
- **Flask & Node.js**: Write logs to `stdout` and `stderr`. Do not concern the app with routing or storage of logs.
### XII. Admin processes
**Run admin/management tasks as one-off processes**
- **Flask & Node.js**: Use scripts that can be run from the command line for tasks like database migrations. These should be run as one-off processes in the execution environment.
## Examples
### Flask Example: Environment Configuration
```python
from flask import Flask
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
# Rest of the Flask app...
```
### Node.js Example: Dependency Declaration and Process Management
```javascript
// package.json snippet
{
"dependencies": {
"express": "^4.17.1",
"dotenv": "^8.2.0"
}
}
// server.js
require('dotenv').config();
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
// Rest of the Node.js app...
```
## Cheat Sheet
- **Codebase**: One codebase per service, tracked in version control.
- **Dependencies**: Declare and isolate dependencies explicitly.
- **Config**: Store configuration in the environment.
- **Backing Services**: Treat backing services as attached resources.
- **Build, Release, Run**: Separate build and run stages.
- **Processes**: Execute the app as one or more stateless processes.
- **Port Binding**: Export services via port binding.
- **Concurrency**: Scale out via the process model.
- **Disposability**: Fast startup and graceful shutdown.
- **Dev/Prod Parity**: Keep development, staging, and production as similar as possible.
- **Logs**: Treat logs as event streams.
- **Admin Processes**: Run admin/management tasks as one-off processes.
## Exercise
Create a simple CRUD (Create, Read, Update, Delete) application using Flask or Node.js applying the twelve-factor methodology. Ensure that:
- Your codebase is tracked in Git.
- All dependencies are explicitly declared.
- Configuration is stored in environment variables.
- You can run your application using a process manager.
- You write logs to `stdout` and `stderr`.
- You can execute a database migration as a one-off process.
## Additional Resources
- [Flask Documentation](https://flask.palletsprojects.com/en/2.0.x/)
- [Node.js Documentation](https://nodejs.org/en/docs/)
- [The Twelve-Factor App](https://12factor.net/)
Remember, the key to mastering the Twelve-Factor App methodology is consistent practice and application in real-world projects. Try to refactor an existing project or start a new one with these principles in mind.