I think Beyond the Twelve-Factor App 1 is a good document, but I also think the purpose and reason for each item is not clear.
This may go without saying, but I think it would be unsettling if it were not clear.
Beyond the Twelve-Factor App has the following 15 items. In order of priority.
- One codebase, one application
- API first
- Dependency management
- Design, build, release, and run
- Configuration, credentials, and code
- Backing services
- Environment parity
- Administrative processes
- Port binding
- Stateless processes
- Authentication and authorization
In this document, I have summarized the purpose and tasks of each of them.
Some parts of this document are my own compositions.
I may have misunderstood the intent of the original document due to my lack of understanding or misunderstanding.
I welcome your pointing out the mistakes. 2
As a precursor to Beyond the Twelve-Factor App, there is a document called The Twelve-Factor App 3.
This is about the methodology for building out Software as a Service, written by the guys at heroku.
Beyond the Twelve-Factor App adds content and details to the original Twelve-Factor App, written by the folks at pivotal.
- I want to automate build and deployment. If an app is split into multiple repositories, it becomes difficult to automate.
- If multiple apps or multiple teams share one repository, it is more natural to follow Conway's Law 4.
Make application and its repositories one-to-one, or one application and multiple repositories that share a common root.
- I want to have a resource to discuss user stories and features with stakeholders.
- I want to avoid mistakes when integrating with other systems.
Make the your API as a first-class artifact of the development process. 5.
We want to make sure that the application does not depend on the configuration of the running environment. We want to do repeatable deployments easily.
Define dependency for each application.Make no assumptions about what is installed and what libraries and tools are available in the production environment.
We want to maximize your delivery speed while keeping the developer's high confidence.
Divide the flow from development to operation into four parts: design, build, release, and run. Each of them should be executed independently. The details are as follows.
Design the next feature to be released.
There is an overall design, but it will change, so it should be done a little at a time in each iteration.
This is also the time to decide which libraries should be used.
Code is converted into binary artifacts (i.e., builds), and CI tools should be used. One build will be released to multiple environments. (Test, QA, production, etc.)
If you have a "it only works in my environment" problem, it means that the four steps in this section are not properly separated.
Release is the process of adding environment-specific and application-specific settings to the build.
Each release should have a unique ID and should be immutable.
It can be used for troubleshooting and rollback.
Once released to the environment, the cloud provider executes it.
The cloud execution environment is responsible for running, health-checking, and logging the app, as well as management tasks for dynamic scaling and fault tolerance.
If you put configuration and code under the same management, it became to hard to manage the configuration for each environment. If you put credentials and code under the same management, many developers can see them. It is not desirable.
Manage configuration, credential, and code separately. The authentication information and configuration should be environment variables, and injected in the build product at the time of release.
We want to simplify the application by making it does not manage the log information.When the number of app execution environments increases dynamically, a log file is created for each environment. We want to manage/analyze such log information easily.
Treat the log as event streams. As an application, don't care where it is placed, and just output the log to
stderr. Use another tool or system to collect and analyze the output.
App developers tend to elaborate on the design of log output, but they should stop doing it in the app but only generate log message to stdout.
You want to be able to scale, deploy, release, and recover your app quickly.
Make it easy to discard the execution process. Also, make it possible to start and stop the app quickly. If your application require a lengthy cache initialization process,you should separate it to backing services, if possible.
I want to be able to connect and disconnect services that my app depends on easily and freely. This is useful in case of failures.
Declare the services that the app depends on (i.e. backing services). Use the cloud environment functions to actually connect them.
You want the entire team to be confident that the app will work in any environment. I mean the environments are development environment, test environment, QA environment, production environment and so on.
Make sure that all environments are the same.
Differences are likely to occur in the following cases. It is generally human error.
- The time between code revision and release is long. Forgetting what modifications or environment changes have been made.
- The release is done manually. Since manual work is always wrong in the first place, it becomes a difference.
- It is difficult and tedious to prepare the same backing service as the production one. Then they substitute a similar but different one, which becomes a difference.
What is Administrative Processes?
- Database migrations
- Interactive programming consoles (REPLs)
- Running timed scripts, such as a nightly batch job or hourly import
- Running a one-off job that executes custom code only once
In the original 12factor, it was a function of the application. The original 12factor says to do these processes as part of the app's functionality, but this should be stopped and some different approach should be considered. When the app scales horizontally, only one instance of the app will be able to run these functions.
Don't run the management process as a function of the application. Consider a different approach for one-time processes, timed batches, etc.
Instead of using cron for regular batches, it is better to prepare a RESTful endpoint and launch it from outside at regular intervals. Or, extract the batch-related code and make it a separate microservice.
- When scaling horizontally, it is difficult to configure all network settings such as routing, scaling, high availability, fault tolerance, etc by hand. The cloud provider should do it.
- When putting multiple apps on a single server, you don't want to manage the ports used by the apps in detail.
The app developer decides which port to provide externally for each app. The cloud provider connects that port to the actual published port.
We want to make it easy to start and stop the server so that we can quickly stop and scale the server at any time.
Have no data in the server that can be passed on between multiple requests. 6
Keep it in the backing service if needed.
When augmenting servers, we want to scale horizontally; we don't want to augment one machine, we want to scale by increasing the number of servers.
Design your application in a configuration where there are multiple processes to process. If the processes are separated into processes, it is easier to distribute the processes across multiple machines.
You want to effectively log your system. In cloud-native apps, you don't always have direct access to the actual server. If the server scales and the number of instances increases 100-fold, the amount of logs can also increase 100-fold.
Consider about how to measure the performance of the application.
Performance may include the following
- Application performance monitoring (APM)
- E.g., number of HTTP processes per second
- Domain-specific telemetry
- e.g., how many products were sold via iPad in the last 20 minutes
- Health and system logs
- e.g., system health check information. Event information such as start, stop, scale, etc.
There is no specific requirement to do this, but it seems to say that we need to be aware of how to capture and consider the content.
Implement security design/implementation from day one of development.
Security is very important whether you are in a cloud environment or not. It should not be an afterthought.
Beyond the Twelve-Factor App
The Twelve-Factor App
How about playing around to find the mistakes? ↩
"Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure." https://en.wikipedia.org/wiki/Conway%27s_law ↩
This item is an extension of the contract-first development style. Roughly speaking, it means determining the specifications that the service will provide for the outside world. ↩
If we say this in Java Servlet, don't have variables in session scope or application scope. ↩