{"id":9285,"date":"2016-02-12T14:04:00","date_gmt":"2016-02-12T13:04:00","guid":{"rendered":"https:\/\/thecamels.org\/the-twelve-factor-app-aplikacja-dwunastu-czynnikow\/"},"modified":"2021-01-13T08:13:31","modified_gmt":"2021-01-13T07:13:31","slug":"the-twelve-factor-app","status":"publish","type":"post","link":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/","title":{"rendered":"The twelve-factor app"},"content":{"rendered":"\n<p>Nowadays, software is widely delivered as a service (web application or SaaS). The twelve-factor app is a methodology that allows you to build such applications in a scalable horizontal way. It includes experience and observations from building a wide range of SaaS applications.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>In the modern era, software is commonly delivered as a service: called&nbsp;<em>web apps<\/em>, or&nbsp;<em>software-as-a-service<\/em>. The twelve-factor app is a methodology for building software-as-a-service apps that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Use&nbsp;<strong>declarative<\/strong>&nbsp;formats for setup automation, to minimize time and cost for new developers joining the project;<\/li><li>Have a&nbsp;<strong>clean contract<\/strong>&nbsp;with the underlying operating system, offering&nbsp;<strong>maximum portability<\/strong>&nbsp;between execution environments;<\/li><li>Are suitable for&nbsp;<strong>deployment<\/strong>&nbsp;on modern&nbsp;<strong>cloud platforms<\/strong>, obviating the need for servers and systems administration;<\/li><li><strong>Minimize divergence<\/strong>&nbsp;between development and production, enabling&nbsp;<strong>continuous deployment<\/strong>&nbsp;for maximum agility;<\/li><li>And can&nbsp;<strong>scale up<\/strong>&nbsp;without significant changes to tooling, architecture, or development practices.<br><\/li><\/ul>\n\n\n\n<p>The twelve-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc).<br><\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Spis tre\u015bci<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#background\" >Background<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#who-should-read-this-document\" >Who should read this document?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#the-twelve-factors\" >The Twelve Factors<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#i-codebase\" >I. Codebase<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#ii-dependencies\" >II. Dependencies<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#iii-config\" >III. Config<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#iv-backing-services\" >IV. Backing services<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#v-build-release-run\" >V. Build, release, run<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#vi-processes\" >VI. Processes<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#vii-port-binding\" >VII. Port binding<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#viii-concurrency\" >VIII. Concurrency<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#ix-disposability\" >IX. Disposability<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#x-devprod-parity\" >X. Dev\/prod parity<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#xi-logs\" >XI. Logs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#xii-admin-processes\" >XII. Admin processes<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"background\"><\/span>Background<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The contributors to this document have been directly involved in the development and deployment of hundreds of apps, and indirectly witnessed the development, operation, and scaling of hundreds of thousands of apps via our work on the&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/www.heroku.com\/\" target=\"_blank\"><span>Heroku<\/span><\/a> platform.<br><\/p>\n\n\n\n<p>This document synthesizes all of our experience and observations on a wide variety of software-as-a-service apps in the wild. It is a triangulation on ideal practices for app development, paying particular attention to the dynamics of the organic growth of an app over time, the dynamics of collaboration between developers working on the app\u2019s codebase, and&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/blog.heroku.com\/archives\/2011\/6\/28\/the_new_heroku_4_erosion_resistance_explicit_contracts\/\" target=\"_blank\"><span>avoiding the cost of software erosion<\/span><\/a>.<br><\/p>\n\n\n\n<p>Our motivation is to raise awareness of some systemic problems we\u2019ve seen in modern application development, to provide a shared vocabulary for discussing those problems, and to offer a set of broad conceptual solutions to those problems with accompanying terminology. The format is inspired by Martin Fowler\u2019s books&nbsp;<em><a rel=\"noreferrer noopener\" href=\"https:\/\/books.google.com\/books\/about\/Patterns_of_enterprise_application_archi.html?id=FyWZt5DdvFkC\" target=\"_blank\"><span>Patterns of Enterprise Application Architecture<\/span><\/a><\/em>&nbsp;and&nbsp;<em><a rel=\"noreferrer noopener\" href=\"https:\/\/books.google.com\/books\/about\/Refactoring.html?id=1MsETFPD3I0C\" target=\"_blank\"><span>Refactoring<\/span><\/a><\/em>.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"who-should-read-this-document\"><\/span>Who should read this document?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Any developer building applications which run as a service. Ops engineers who deploy or manage such applications.<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"the-twelve-factors\"><\/span>The Twelve Factors<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"i-codebase\"><\/span>I. Codebase<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>One codebase tracked in revision control, many deploys<\/p><\/blockquote>\n\n\n\n<p>A twelve-factor app is always tracked in a version control system, such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/git-scm.com\/\"><span>Git<\/span><\/a>,&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/www.mercurial-scm.org\/\"><span>Mercurial<\/span><\/a>, or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/subversion.apache.org\/\"><span>Subversion<\/span><\/a>. A copy of the revision tracking database is known as a&nbsp;<em>code repository<\/em>, often shortened to&nbsp;<em>code repo<\/em>&nbsp;or just&nbsp;<em>repo<\/em>.<br><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"390\" height=\"325\" src=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/codebase-deploys.png\" alt=\"A codebase is any single repo.\" class=\"wp-image-4971\" srcset=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/codebase-deploys.png 390w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/codebase-deploys-300x250.png 300w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/codebase-deploys-130x108.png 130w\" sizes=\"auto, (max-width: 390px) 100vw, 390px\" \/><\/figure><\/div>\n\n\n\n<p>A&nbsp;<em>codebase<\/em>&nbsp;is any single repo (in a centralized revision control system like Subversion), or any set of repos who share a root commit (in a decentralized revision control system like Git).<br><\/p>\n\n\n\n<p>There is always a one-to-one correlation between the codebase and the app:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>If there are multiple codebases, it\u2019s not an app \u2013 it\u2019s a distributed system. Each component in a distributed system is an app, and each can individually comply with twelve-factor.<br><\/li><li>Multiple apps sharing the same code is a violation of twelve-factor. The solution here is to factor shared code into libraries which can be included through the&nbsp;dependency manager.<br><\/li><\/ul>\n\n\n\n<p>There is only one codebase per app, but there will be many deploys of the app. A&nbsp;<em>deploy<\/em>&nbsp;is a running instance of the app. This is typically a production site, and one or more staging sites. Additionally, every developer has a copy of the app running in their local development environment, each of which also qualifies as a deploy.<br><\/p>\n\n\n\n<p>The codebase is the same across all deploys, although different versions may be active in each deploy. For example, a developer has some commits not yet deployed to staging; staging has some commits not yet deployed to production. But they all share the same codebase, thus making them identifiable as different deploys of the same app.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ii-dependencies\"><\/span>II. Dependencies<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Explicitly declare and isolate dependencies<\/p><\/blockquote>\n\n\n\n<p>Most programming languages offer a packaging system for distributing support libraries, such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.cpan.org\/\"><span>CPAN<\/span><\/a>&nbsp;for Perl or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/rubygems.org\/\"><span>Rubygems<\/span><\/a>for Ruby. Libraries installed through a packaging system can be installed system-wide (known as \u201csite packages\u201d) or scoped into the directory containing the app (known as \u201cvendoring\u201d or \u201cbundling\u201d).<br><\/p>\n\n\n\n<p><strong>A twelve-factor app never relies on implicit existence of system-wide packages.<\/strong>&nbsp;It declares all dependencies, completely and exactly, via a&nbsp;<em>dependency declaration<\/em>&nbsp;manifest. Furthermore, it uses a&nbsp;<em>dependency isolation<\/em>&nbsp;tool during execution to ensure that no implicit dependencies \u201cleak in\u201d from the surrounding system. The full and explicit dependency specification is applied uniformly to both production and development.<br><\/p>\n\n\n\n<p>For example,&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/bundler.io\/\"><span>Bundler<\/span><\/a>&nbsp;for Ruby offers the&nbsp;<code>Gemfile<\/code>&nbsp;manifest format for dependency declaration and&nbsp;<code>bundle exec<\/code>&nbsp;for dependency isolation. In Python there are two separate tools for these steps \u2013&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.pip-installer.org\/en\/latest\/\"><span>Pip<\/span><\/a>&nbsp;is used for declaration and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.virtualenv.org\/en\/latest\/\"><span>Virtualenv<\/span><\/a>&nbsp;for isolation. Even C has&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.gnu.org\/s\/autoconf\/\"><span>Autoconf<\/span><\/a>&nbsp;for dependency declaration, and static linking can provide dependency isolation. No matter what the toolchain, dependency declaration and isolation must always be used together \u2013 only one or the other is not sufficient to satisfy twelve-factor.<br><\/p>\n\n\n\n<p>One benefit of explicit dependency declaration is that it simplifies setup for developers new to the app. The new developer can check out the app\u2019s codebase onto their development machine, requiring only the language runtime and dependency manager installed as prerequisites. They will be able to set up everything needed to run the app\u2019s code with a deterministic&nbsp;<em>build command<\/em>. For example, the build command for Ruby\/Bundler is&nbsp;<code>bundle install<\/code>, while for Clojure\/<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/technomancy\/leiningen#readme\"><span>Leiningen<\/span><\/a>&nbsp;it is&nbsp;<code>lein deps<\/code>.<\/p>\n\n\n\n<p>Twelve-factor apps also do not rely on the implicit existence of any system tools. Examples include shelling out to ImageMagick or&nbsp;<code>curl<\/code>. While these tools may exist on many or even most systems, there is no guarantee that they will exist on all systems where the app may run in the future, or whether the version found on a future system will be compatible with the app. If the app needs to shell out to a system tool, that tool should be vendored into the app.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"iii-config\"><\/span>III. Config<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Store config in the environment<\/p><\/blockquote>\n\n\n\n<p>An app\u2019s&nbsp;<em>config<\/em>&nbsp;is everything that is likely to vary between&nbsp;deploys&nbsp;(staging, production, developer environments, etc). This includes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Resource handles to the database, Memcached, and other&nbsp;backing services<\/li><li>Credentials to external services such as Amazon S3 or Twitter<\/li><li>Per-deploy values such as the canonical hostname for the deploy<\/li><\/ul>\n\n\n\n<p>Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires&nbsp;<strong>strict separation of config from code<\/strong>. Config varies substantially across deploys, code does not.<\/p>\n\n\n\n<p>A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be made open source at any moment, without compromising any credentials.<\/p>\n\n\n\n<p>Note that this definition of \u201cconfig\u201d does&nbsp;<strong>not<\/strong>&nbsp;include internal application config, such as&nbsp;<code>config\/routes.rb<\/code>&nbsp;in Rails, or how&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/docs.spring.io\/spring\/docs\/current\/spring-framework-reference\/html\/beans.html\"><span>code modules are connected<\/span><\/a>&nbsp;in&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/spring.io\/\"><span>Spring<\/span><\/a>. This type of config does not vary between deploys, and so is best done in the code.<\/p>\n\n\n\n<p>Another approach to config is the use of config files which are not checked into revision control, such as&nbsp;<code>config\/database.yml<\/code>&nbsp;in Rails. This is a huge improvement over using constants which are checked into the code repo, but still has weaknesses: it\u2019s easy to mistakenly check in a config file to the repo; there is a tendency for config files to be scattered about in different places and different formats, making it hard to see and manage all the config in one place. Further, these formats tend to be language- or framework-specific.<\/p>\n\n\n\n<p><strong>The twelve-factor app stores config in&nbsp;<em>environment variables<\/em><\/strong>&nbsp;(often shortened to&nbsp;<em>env vars<\/em>&nbsp;or&nbsp;<em>env<\/em>). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.<\/p>\n\n\n\n<p>Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called \u201cenvironments\u201d) named after specific deploys, such as the&nbsp;<code>development<\/code>,&nbsp;<code>test<\/code>, and&nbsp;<code>production<\/code>&nbsp;environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as&nbsp;<code>staging<\/code>&nbsp;or&nbsp;<code>qa<\/code>. As the project grows further, developers may add their own special environments like&nbsp;<code>joes-staging<\/code>, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle.<\/p>\n\n\n\n<p>In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as \u201cenvironments\u201d, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"iv-backing-services\"><\/span>IV. Backing services<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Traktuj us\u0142ugi tworzenia kopii zapasowych jako do\u0142\u0105czone zasoby<\/p><\/blockquote>\n\n\n\n<p>A&nbsp;<em>backing service<\/em>&nbsp;is any service the app consumes over the network as part of its normal operation. Examples include datastores (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/dev.mysql.com\/\"><span>MySQL<\/span><\/a>&nbsp;or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/couchdb.apache.org\/\"><span>CouchDB<\/span><\/a>), messaging\/queueing systems (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.rabbitmq.com\/\"><span>RabbitMQ<\/span><\/a>&nbsp;or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/beanstalkd.github.io\/\"><span>Beanstalkd<\/span><\/a>), SMTP services for outbound email (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.postfix.org\/\"><span>Postfix<\/span><\/a>), and caching systems (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/memcached.org\/\"><span>Memcached<\/span><\/a>).<\/p>\n\n\n\n<p>Backing services like the database are traditionally managed by the same systems administrators who deploy the app\u2019s runtime. In addition to these locally-managed services, the app may also have services provided and managed by third parties. Examples include SMTP services (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/postmarkapp.com\/\"><span>Postmark<\/span><\/a>), metrics-gathering services (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/newrelic.com\/\"><span>New Relic<\/span><\/a>&nbsp;or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.loggly.com\/\"><span>Loggly<\/span><\/a>), binary asset services (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/aws.amazon.com\/s3\/\"><span>Amazon S3<\/span><\/a>), and even API-accessible consumer services (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/dev.twitter.com\/\"><span>Twitter<\/span><\/a>,&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/developers.google.com\/maps\/\"><span>Google Maps<\/span><\/a>, or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.last.fm\/api\"><span>Last.fm<\/span><\/a>).<\/p>\n\n\n\n<p><strong>The code for a twelve-factor app makes no distinction between local and third party services.<\/strong>&nbsp;To the app, both are attached resources, accessed via a URL or other locator\/credentials stored in the&nbsp;config. A&nbsp;deploy&nbsp;of the twelve-factor app should be able to swap out a local MySQL database with one managed by a third party (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/aws.amazon.com\/rds\/\"><span>Amazon RDS<\/span><\/a>) without any changes to the app\u2019s code. Likewise, a local SMTP server could be swapped with a third-party SMTP service (such as Postmark) without code changes. In both cases, only the resource handle in the config needs to change.<\/p>\n\n\n\n<p>Each distinct backing service is a&nbsp;<em>resource<\/em>. For example, a MySQL database is a resource; two MySQL databases (used for sharding at the application layer) qualify as two distinct resources. The twelve-factor app treats these databases as&nbsp;<em>attached resources<\/em>, which indicates their loose coupling to the deploy they are attached to.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"872\" height=\"454\" src=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources.png\" alt=\"Backing services\" class=\"wp-image-4972\" srcset=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources.png 872w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources-600x312.png 600w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources-768x400.png 768w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources-300x156.png 300w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/attached-resources-130x68.png 130w\" sizes=\"auto, (max-width: 872px) 100vw, 872px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"v-build-release-run\"><\/span>V. Build, release, run<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Wyra\u017anie oddziel etapy budowy i uruchomienia<\/p><\/blockquote>\n\n\n\n<p>A&nbsp;codebase&nbsp;is transformed into a (non-development) deploy through three stages:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The&nbsp;<em>build stage<\/em>&nbsp;is a transform which converts a code repo into an executable bundle known as a&nbsp;<em>build<\/em>. Using a version of the code at a commit specified by the deployment process, the build stage fetches vendors&nbsp;dependencies&nbsp;and compiles binaries and assets.<\/li><li>The&nbsp;<em>release stage<\/em>&nbsp;takes the build produced by the build stage and combines it with the deploy\u2019s current&nbsp;config. The resulting&nbsp;<em>release<\/em>&nbsp;contains both the build and the config and is ready for immediate execution in the execution environment.<\/li><li>The&nbsp;<em>run stage<\/em>&nbsp;(also known as \u201cruntime\u201d) runs the app in the execution environment, by launching some set of the app\u2019s&nbsp;processes&nbsp;against a selected release.<\/li><\/ul>\n\n\n\n<p><strong>The twelve-factor app uses strict separation between the build, release, and run stages.<\/strong>&nbsp;For example, it is impossible to make changes to the code at runtime, since there is no way to propagate those changes back to the build stage.<br><\/p>\n\n\n\n<p>Deployment tools typically offer release management tools, most notably the ability to roll back to a previous release. For example, the&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/capistrano\/capistrano\/wiki\"><span>Capistrano<\/span><\/a>&nbsp;deployment tool stores releases in a subdirectory named&nbsp;<code>releases<\/code>, where the current release is a symlink to the current release directory. Its&nbsp;<code>rollback<\/code>&nbsp;command makes it easy to quickly roll back to a previous release.<br><\/p>\n\n\n\n<p>Every release should always have a unique release ID, such as a timestamp of the release (such as&nbsp;<code>2011-04-06-20:32:17<\/code>) or an incrementing number (such as&nbsp;<code>v100<\/code>). Releases are an append-only ledger and a release cannot be mutated once it is created. Any change must create a new release.<br><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"560\" height=\"233\" src=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/release.png\" alt=\"Every release should always have a unique release ID\" class=\"wp-image-4973\" srcset=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/release.png 560w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/release-300x125.png 300w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/release-130x54.png 130w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/figure><\/div>\n\n\n\n<p>Builds are initiated by the app\u2019s developers whenever new code is deployed. Runtime execution, by contrast, can happen automatically in cases such as a server reboot, or a crashed process being restarted by the process manager. Therefore, the run stage should be kept to as few moving parts as possible, since problems that prevent an app from running can cause it to break in the middle of the night when no developers are on hand. The build stage can be more complex, since errors are always in the foreground for a developer who is driving the deploy.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"vi-processes\"><\/span>VI. Processes<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Wykonuj aplikacj\u0119 jako jeden (lub wi\u0119cej) proces bezstanowy<\/p><\/blockquote>\n\n\n\n<p>The app is executed in the execution environment as one or more&nbsp;<em>processes<\/em>.<br><\/p>\n\n\n\n<p>In the simplest case, the code is a stand-alone script, the execution environment is a developer\u2019s local laptop with an installed language runtime, and the process is launched via the command line (for example,&nbsp;<code>python my_script.py<\/code>). On the other end of the spectrum, a production deploy of a sophisticated app may use many&nbsp;process types, instantiated into zero or more running processes.<\/p>\n\n\n\n<p><strong>Twelve-factor processes are stateless and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/Shared_nothing_architecture\"><span>share-nothing<\/span><\/a>.<\/strong>&nbsp;Any data that needs to persist must be stored in a stateful&nbsp;backing service, typically a database.<\/p>\n\n\n\n<p>The memory space or filesystem of the process can be used as a brief, single-transaction cache. For example, downloading a large file, operating on it, and storing the results of the operation in the database. The twelve-factor app never assumes that anything cached in memory or on disk will be available on a future request or job \u2013 with many processes of each type running, chances are high that a future request will be served by a different process. Even when running only one process, a restart (triggered by code deploy, config change, or the execution environment relocating the process to a different physical location) will usually wipe out all local (e.g., memory and filesystem) state.<\/p>\n\n\n\n<p>Asset packagers like&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/code.google.com\/p\/django-assetpackager\/\"><span>django-assetpackager<\/span><\/a>&nbsp;use the filesystem as a cache for compiled assets. A twelve-factor app prefers to do this compiling during the&nbsp;build stage. Asset packagers such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/documentcloud.github.com\/jammit\/\"><span>Jammit<\/span><\/a>&nbsp;and the&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/ryanbigg.com\/guides\/asset_pipeline.html\"><span>Rails asset pipeline<\/span><\/a>&nbsp;can be configured to package assets during the build stage.<\/p>\n\n\n\n<p>Some web systems rely on&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/Load_balancing_%28computing%29#Persistence\"><span>\u201csticky sessions\u201d<\/span><\/a>&nbsp;\u2013 that is, caching user session data in memory of the app\u2019s process and expecting future requests from the same visitor to be routed to the same process. Sticky sessions are a violation of twelve-factor and should never be used or relied upon. Session state data is a good candidate for a datastore that offers time-expiration, such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/memcached.org\/\"><span>Memcached<\/span><\/a>&nbsp;or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/redis.io\/\"><span>Redis<\/span><\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"vii-port-binding\"><\/span>VII. Port binding<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Export services via port binding<\/p><\/blockquote>\n\n\n\n<p>Web apps are sometimes executed inside a webserver container. For example, PHP apps might run as a module inside&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/httpd.apache.org\/\"><span>Apache HTTPD<\/span><\/a>, or Java apps might run inside&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/tomcat.apache.org\/\"><span>Tomcat<\/span><\/a>.<\/p>\n\n\n\n<p><strong>The twelve-factor app is completely self-contained<\/strong>&nbsp;and does not rely on runtime injection of a webserver into the execution environment to create a web-facing service. The web app&nbsp;<strong>exports HTTP as a service by binding to a port<\/strong>, and listening to requests coming in on that port.<\/p>\n\n\n\n<p>In a local development environment, the developer visits a service URL like&nbsp;<code>http:\/\/localhost:5000\/<\/code>&nbsp;to access the service exported by their app. In deployment, a routing layer handles routing requests from a public-facing hostname to the port-bound web processes.<\/p>\n\n\n\n<p>This is typically implemented by using&nbsp;dependency declaration&nbsp;to add a webserver library to the app, such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.tornadoweb.org\/\"><span>Tornado<\/span><\/a>&nbsp;for Python,&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/code.macournoyer.com\/thin\/\"><span>Thin<\/span><\/a>&nbsp;for Ruby, or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.eclipse.org\/jetty\/\"><span>Jetty<\/span><\/a>&nbsp;for Java and other JVM-based languages. This happens entirely in&nbsp;<em>user space<\/em>, that is, within the app\u2019s code. The contract with the execution environment is binding to a port to serve requests.<\/p>\n\n\n\n<p>HTTP is not the only service that can be exported by port binding. Nearly any kind of server software can be run via a process binding to a port and awaiting incoming requests. Examples include&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.ejabberd.im\/\"><span>ejabberd<\/span><\/a>&nbsp;(speaking&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/xmpp.org\/\"><span>XMPP<\/span><\/a>), and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/redis.io\/\"><span>Redis<\/span><\/a>&nbsp;(speaking the&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/redis.io\/topics\/protocol\"><span>Redis protocol<\/span><\/a>).<\/p>\n\n\n\n<p>Note also that the port-binding approach means that one app can become the&nbsp;backing service&nbsp;for another app, by providing the URL to the backing app as a resource handle in the&nbsp;config&nbsp;for the consuming app.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"viii-concurrency\"><\/span>VIII. Concurrency<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Scale out via the process model<\/p><\/blockquote>\n\n\n\n<p>Any computer program, once run, is represented by one or more processes. Web apps have taken a variety of process-execution forms. For example, PHP processes run as child processes of Apache, started on demand as needed by request volume. Java processes take the opposite approach, with the JVM providing one massive uberprocess that reserves a large block of system resources (CPU and memory) on startup, with concurrency managed internally via threads. In both cases, the running process(es) are only minimally visible to the developers of the app.<br><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"420\" height=\"383\" src=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/process-types.png\" alt=\"Concurrency\" class=\"wp-image-4974\" srcset=\"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/process-types.png 420w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/process-types-300x274.png 300w, https:\/\/thecamels.org\/wp-content\/uploads\/2018\/04\/process-types-130x119.png 130w\" sizes=\"auto, (max-width: 420px) 100vw, 420px\" \/><\/figure><\/div>\n\n\n\n<p><strong>In the twelve-factor app, processes are a first class citizen.<\/strong>&nbsp;Processes in the twelve-factor app take strong cues from&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/adam.herokuapp.com\/past\/2011\/5\/9\/applying_the_unix_process_model_to_web_apps\/\"><span>the unix process model for running service daemons<\/span><\/a>. Using this model, the developer can architect their app to handle diverse workloads by assigning each type of work to a&nbsp;<em>process type<\/em>. For example, HTTP requests may be handled by a web process, and long-running background tasks handled by a worker process.<\/p>\n\n\n\n<p>This does not exclude individual processes from handling their own internal multiplexing, via threads inside the runtime VM, or the async\/evented model found in tools such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/eventmachine\/eventmachine\"><span>EventMachine<\/span><\/a>,&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/twistedmatrix.com\/trac\/\"><span>Twisted<\/span><\/a>, or&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/nodejs.org\/\"><span>Node.js<\/span><\/a>. But an individual VM can only grow so large (vertical scale), so the application must also be able to span multiple processes running on multiple physical machines.<\/p>\n\n\n\n<p>The process model truly shines when it comes time to scale out. The&nbsp;share-nothing, horizontally partitionable nature of twelve-factor app processes&nbsp;means that adding more concurrency is a simple and reliable operation. The array of process types and number of processes of each type is known as the&nbsp;<em>process formation<\/em>.<\/p>\n\n\n\n<p>Twelve-factor app processes&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/dustin.github.com\/2010\/02\/28\/running-processes.html\"><span>should never daemonize<\/span><\/a>&nbsp;or write PID files. Instead, rely on the operating system\u2019s process manager (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/\"><span>systemd<\/span><\/a>, a distributed process manager on a cloud platform, or a tool like&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/blog.daviddollar.org\/2011\/05\/06\/introducing-foreman.html\"><span>Foreman<\/span><\/a>&nbsp;in development) to manage&nbsp;output streams, respond to crashed processes, and handle user-initiated restarts and shutdowns.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ix-disposability\"><\/span>IX. Disposability<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Maximize robustness with fast startup and graceful shutdown<br><\/p><\/blockquote>\n\n\n\n<p><strong>The twelve-factor app\u2019s&nbsp;processes&nbsp;are&nbsp;<em>disposable<\/em>, meaning they can be started or stopped at a moment\u2019s notice.<\/strong>&nbsp;This facilitates fast elastic scaling, rapid deployment of&nbsp;code&nbsp;or&nbsp;config&nbsp;changes, and robustness of production deploys.<\/p>\n\n\n\n<p>Processes should strive to&nbsp;<strong>minimize startup time<\/strong>. Ideally, a process takes a few seconds from the time the launch command is executed until the process is up and ready to receive requests or jobs. Short startup time provides more agility for the&nbsp;release&nbsp;process and scaling up; and it aids robustness, because the process manager can more easily move processes to new physical machines when warranted.<\/p>\n\n\n\n<p>Processes&nbsp;<strong>shut down gracefully when they receive a&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/SIGTERM\"><span>SIGTERM<\/span><\/a><\/strong>&nbsp;signal from the process manager. For a web process, graceful shutdown is achieved by ceasing to listen on the service port (thereby refusing any new requests), allowing any current requests to finish, and then exiting. Implicit in this model is that HTTP requests are short (no more than a few seconds), or in the case of long polling, the client should seamlessly attempt to reconnect when the connection is lost.<\/p>\n\n\n\n<p>For a worker process, graceful shutdown is achieved by returning the current job to the work queue. For example, on&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.rabbitmq.com\/\"><span>RabbitMQ<\/span><\/a>&nbsp;the worker can send a&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.rabbitmq.com\/amqp-0-9-1-quickref.html#basic.nack\"><span><code>NACK<\/code><\/span><\/a>; on&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/beanstalkd.github.io\/\"><span>Beanstalkd<\/span><\/a>, the job is returned to the queue automatically whenever a worker disconnects. Lock-based systems such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/collectiveidea\/delayed_job#readme\"><span>Delayed Job<\/span><\/a>&nbsp;need to be sure to release their lock on the job record. Implicit in this model is that all jobs are&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/Reentrant_%28subroutine%29\"><span>reentrant<\/span><\/a>, which typically is achieved by wrapping the results in a transaction, or making the operation&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/Idempotence\"><span>idempotent<\/span><\/a>.<\/p>\n\n\n\n<p>Processes should also be&nbsp;<strong>robust against sudden death<\/strong>, in the case of a failure in the underlying hardware. While this is a much less common occurrence than a graceful shutdown with&nbsp;<code>SIGTERM<\/code>, it can still happen. A recommended approach is use of a robust queueing backend, such as Beanstalkd, that returns jobs to the queue when clients disconnect or time out. Either way, a twelve-factor app is architected to handle unexpected, non-graceful terminations.&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/lwn.net\/Articles\/191059\/\"><span>Crash-only design<\/span><\/a>&nbsp;takes this concept to its&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/docs.couchdb.org\/en\/latest\/intro\/overview.html\"><span>logical conclusion<\/span><\/a>.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"x-devprod-parity\"><\/span>X. Dev\/prod parity<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Keep development, staging, and production as similar as possible<br><\/p><\/blockquote>\n\n\n\n<p>Historically, there have been substantial gaps between development (a developer making live edits to a local&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/12factor.net\/codebase\"><span>deploy<\/span><\/a>&nbsp;of the app) and production (a running deploy of the app accessed by end users). These gaps manifest in three areas:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>The time gap<\/strong>: A developer may work on code that takes days, weeks, or even months to go into production.<\/li><li><strong>The personnel gap<\/strong>: Developers write code, ops engineers deploy it.<\/li><li><strong>The tools gap<\/strong>: Developers may be using a stack like Nginx, SQLite, and OS X, while the production deploy uses Apache, MySQL, and Linux.<\/li><\/ul>\n\n\n\n<p><strong>The twelve-factor app is designed for&nbsp;continuous deployment&nbsp;by keeping the gap between development and production small.<\/strong>&nbsp;Looking at the three gaps described above:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Utrzymuj niewielkie przerwy: deweloper mo\u017ce napisa\u0107 kod i wdro\u017cy\u0107 kilka godzin lub nawet kilka minut p\u00f3\u017aniej.<\/li><li>Sprawy, by przerwa w personelu by\u0142a niewielka: deweloperzy, kt\u00f3rzy pisz\u0105 kod s\u0105 \u015bci\u015ble zaanga\u017cowani w jego wdra\u017canie i obserwuj\u0105 zachowanie kodu w produkcji.<\/li><li>Utrzymuj ma\u0142\u0105 przerw\u0119 w narz\u0119dziach: spraw, aby rozw\u00f3j i produkcja by\u0142y mo\u017cliwie najbardziej zbli\u017cone.<\/li><\/ul>\n\n\n\n<p>Podsumowuj\u0105c powy\u017csze w tabeli:<\/p>\n\n\n<table>\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td><strong>Traditional app<\/strong><\/td>\n<td><strong>Twelve-factor app<\/strong><\/td>\n<\/tr>\n<tr>\n<td><strong>Time between deploys<\/strong><\/td>\n<td>Weeks<\/td>\n<td>Hours<\/td>\n<\/tr>\n<tr>\n<td><strong>Code authors vs code deployers<\/strong><\/td>\n<td>Different people<\/td>\n<td>Same people<\/td>\n<\/tr>\n<tr>\n<td><strong>Dev vs production environments<\/strong><\/td>\n<td>Divergent<\/td>\n<td>As similar as possible<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n\n<p><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/12factor.net\/backing-services\"><span>Backing services<\/span><\/a>, such as the app\u2019s database, queueing system, or cache, is one area where dev\/prod parity is important. Many languages offer libraries which simplify access to the backing service, including&nbsp;<em>adapters<\/em>&nbsp;to different types of services. Some examples are in the table below.<br><\/p>\n\n\n<table>\n<tbody>\n<tr>\n<td><strong>Type<\/strong><\/td>\n<td><strong>Language<\/strong><\/td>\n<td><strong>Library<\/strong><\/td>\n<td><strong>Adapters<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Database<\/td>\n<td>Ruby\/Rails<\/td>\n<td>ActiveRecord<\/td>\n<td>MySQL, PostgreSQL, SQLite<\/td>\n<\/tr>\n<tr>\n<td>Queue<\/td>\n<td>Python\/Django<\/td>\n<td>Celery<\/td>\n<td>RabbitMQ, Beanstalkd, Redis<\/td>\n<\/tr>\n<tr>\n<td>Cache<\/td>\n<td>Ruby\/Rails<\/td>\n<td>ActiveSupport::Cache<\/td>\n<td>Pami\u0119\u0107, system plik\u00f3w, Memcached<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n\n<p>Developers sometimes find great appeal in using a lightweight backing service in their local environments, while a more serious and robust backing service will be used in production. For example, using SQLite locally and PostgreSQL in production; or local process memory for caching in development and Memcached in production.<br><\/p>\n\n\n\n<p><strong>The twelve-factor developer resists the urge to use different backing services between development and production<\/strong>, even when adapters theoretically abstract away any differences in backing services. Differences between backing services mean that tiny incompatibilities crop up, causing code that worked and passed tests in development or staging to fail in production. These types of errors create friction that disincentivizes continuous deployment. The cost of this friction and the subsequent dampening of continuous deployment is extremely high when considered in aggregate over the lifetime of an application.<br><\/p>\n\n\n\n<p>Lightweight local services are less compelling than they once were. Modern backing services such as Memcached, PostgreSQL, and RabbitMQ are not difficult to install and run thanks to modern packaging systems, such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/mxcl.github.com\/homebrew\/\"><span>Homebrew<\/span><\/a>&nbsp;and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/help.ubuntu.com\/community\/AptGet\/Howto\"><span>apt-get<\/span><\/a>. Alternatively, declarative provisioning tools such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.opscode.com\/chef\/\"><span>Chef<\/span><\/a>&nbsp;and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/docs.puppetlabs.com\/\"><span>Puppet<\/span><\/a>&nbsp;combined with light-weight virtual environments such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/www.docker.com\/\"><span>Docker<\/span><\/a>&nbsp;and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/vagrantup.com\/\"><span>Vagrant<\/span><\/a>&nbsp;allow developers to run local environments which closely approximate production environments. The cost of installing and using these systems is low compared to the benefit of dev\/prod parity and continuous deployment.<br><\/p>\n\n\n\n<p>Adapters to different backing services are still useful, because they make porting to new backing services relatively painless. But all deploys of the app (developer environments, staging, production) should be using the same type and version of each of the backing services.<br><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"xi-logs\"><\/span>XI. Logs<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Treat logs as event streams<\/p><\/blockquote>\n\n\n\n<p><em>Logs<\/em>&nbsp;provide visibility into the behavior of a running app. In server-based environments they are commonly written to a file on disk (a \u201clogfile\u201d); but this is only an output format.<br><\/p>\n\n\n\n<p>Logs are the&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/adam.herokuapp.com\/past\/2011\/4\/1\/logs_are_streams_not_files\/\"><span>stream<\/span><\/a>&nbsp;of aggregated, time-ordered events collected from the output streams of all running processes and backing services. Logs in their raw form are typically a text format with one event per line (though backtraces from exceptions may span multiple lines). Logs have no fixed beginning or end, but flow continuously as long as the app is operating.<br><\/p>\n\n\n\n<p><strong>A twelve-factor app never concerns itself with routing or storage of its output stream.<\/strong>&nbsp;It should not attempt to write to or manage logfiles. Instead, each running process writes its event stream, unbuffered, to&nbsp;<code>stdout<\/code>. During local development, the developer will view this stream in the foreground of their terminal to observe the app\u2019s behavior.<br><\/p>\n\n\n\n<p>In staging or production deploys, each process\u2019 stream will be captured by the execution environment, collated together with all other streams from the app, and routed to one or more final destinations for viewing and long-term archival. These archival destinations are not visible to or configurable by the app, and instead are completely managed by the execution environment. Open-source log routers (such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/heroku\/logplex\"><span>Logplex<\/span><\/a>&nbsp;and&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/github.com\/fluent\/fluentd\"><span>Fluentd<\/span><\/a>) are available for this purpose.<br><\/p>\n\n\n\n<p>The event stream for an app can be routed to a file, or watched via realtime tail in a terminal. Most significantly, the stream can be sent to a log indexing and analysis system such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/www.splunk.com\/\"><span>Splunk<\/span><\/a>, or a general-purpose data warehousing system such as&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/hive.apache.org\/\"><span>Hadoop\/Hive<\/span><\/a>. These systems allow for great power and flexibility for introspecting an app\u2019s behavior over time, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Finding specific events in the past.<\/li><li>Large-scale graphing of trends (such as requests per minute).<\/li><li>Active alerting according to user-defined heuristics (such as an alert when the quantity of errors per minute exceeds a certain threshold).<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"xii-admin-processes\"><\/span>XII. Admin processes<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Run admin\/management tasks as one-off processes<\/p><\/blockquote>\n\n\n\n<p>The&nbsp;process formation&nbsp;is the array of processes that are used to do the app\u2019s regular business (such as handling web requests) as it runs. Separately, developers will often wish to do one-off administrative or maintenance tasks for the app, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Running database migrations (e.g.&nbsp;<code>manage.py migrate<\/code>&nbsp;in Django,&nbsp;<code>rake db:migrate<\/code>&nbsp;in Rails).<\/li><li>Running a console (also known as a&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\/\/en.wikipedia.org\/wiki\/Read-eval-print_loop\"><span>REPL<\/span><\/a>&nbsp;shell) to run arbitrary code or inspect the app\u2019s models against the live database. Most languages provide a REPL by running the interpreter without any arguments (e.g.&nbsp;<code>python<\/code>&nbsp;or&nbsp;<code>perl<\/code>) or in some cases have a separate command (e.g.&nbsp;<code>irb<\/code>&nbsp;for Ruby,&nbsp;<code>rails console<\/code>&nbsp;for Rails).<\/li><li>Running one-time scripts committed into the app\u2019s repo (e.g.&nbsp;<code>php scripts\/fix_bad_records.php<\/code>).<\/li><\/ul>\n\n\n\n<p>One-off admin processes should be run in an identical environment as the regular&nbsp;<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/12factor.net\/processes\"><span>long-runn<\/span><\/a>i<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/12factor.net\/processes\"><span>ng processes<\/span><\/a>&nbsp;of the app. They run against a&nbsp;release, using the same&nbsp;codebase&nbsp;and&nbsp;config&nbsp;as any process run against that release. Admin code must ship with application code to avoid synchronization issues.<\/p>\n\n\n\n<p>The same&nbsp;dependency isolation&nbsp;techniques should be used on all process types. For example, if the Ruby web process uses the command&nbsp;<code>bundle exec thin start<\/code>, then a database migration should use&nbsp;<code>bundle exec rake db:migrate<\/code>. Likewise, a Python program using Virtualenv should use the vendored&nbsp;<code>bin\/python<\/code>&nbsp;for running both the Tornado webserver and any&nbsp;<code>manage.py<\/code>&nbsp;admin processes.<\/p>\n\n\n\n<p>Twelve-factor strongly favors languages which provide a REPL shell out of the box, and which make it easy to run one-off scripts. In a local deploy, developers invoke one-off admin processes by a direct shell command inside the app\u2019s checkout directory. In a production deploy, developers can use ssh or other remote command execution mechanism provided by that deploy\u2019s execution environment to run such a process.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nowadays, software is widely delivered as a service (web application or SaaS). The twelve-factor app is a methodology that allows you to build such applications in a scalable horizontal way. It includes experience and observations from building a wide range of SaaS applications.<\/p>\n","protected":false},"author":1,"featured_media":17185,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[150],"tags":[699],"class_list":["post-9285","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-server-administration"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The twelve-factor app - Thecamels.org<\/title>\n<meta name=\"description\" content=\"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The twelve-factor app - Thecamels.org\" \/>\n<meta property=\"og:description\" content=\"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/?utm_source=dark&amp;utm_medium=social&amp;utm_campaign=open-graph\" \/>\n<meta property=\"og:site_name\" content=\"Thecamels.org\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/thecamels.org\/\" \/>\n<meta property=\"article:published_time\" content=\"2016-02-12T13:04:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T07:13:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/17.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"627\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kamil Porembi\u0144ski\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/17.png\" \/>\n<meta name=\"twitter:creator\" content=\"@thecamelsorg\" \/>\n<meta name=\"twitter:site\" content=\"@thecamelsorg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kamil Porembi\u0144ski\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/\"},\"author\":{\"name\":\"Kamil Porembi\u0144ski\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#\\\/schema\\\/person\\\/b7bd2aec5f506a68323eb40c86d38a32\"},\"headline\":\"The twelve-factor app\",\"datePublished\":\"2016-02-12T13:04:00+00:00\",\"dateModified\":\"2021-01-13T07:13:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/\"},\"wordCount\":4813,\"publisher\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/18.png\",\"keywords\":[\"server administration\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/\",\"url\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/\",\"name\":\"The twelve-factor app - Thecamels.org\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/18.png\",\"datePublished\":\"2016-02-12T13:04:00+00:00\",\"dateModified\":\"2021-01-13T07:13:31+00:00\",\"description\":\"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#primaryimage\",\"url\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/18.png\",\"contentUrl\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/18.png\",\"width\":1200,\"height\":627,\"caption\":\"The twelve-factor app - aplikacja dwunastu czynnik\u00f3w\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/the-twelve-factor-app\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"[HOME]\",\"item\":\"https:\\\/\\\/thecamels.org\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/thecamels.org\\\/en\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"The twelve-factor app\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/thecamels.org\\\/en\\\/\",\"name\":\"Thecamels.org\",\"description\":\"Hosting SSD NVMe z certyfikatem SSL i HTTP\\\/2. Administracja serwerami, skalowanie infrastruktury. Mamy g\u0142ow\u0119 do serwer\u00f3w i zadbamy o Twoj\u0105 stron\u0119 w sieci.\",\"publisher\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/thecamels.org\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#organization\",\"name\":\"Thecamels\",\"url\":\"https:\\\/\\\/thecamels.org\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2018\\\/09\\\/TC-logo-nowe.png\",\"contentUrl\":\"https:\\\/\\\/thecamels.org\\\/wp-content\\\/uploads\\\/2018\\\/09\\\/TC-logo-nowe.png\",\"width\":826,\"height\":106,\"caption\":\"Thecamels\"},\"image\":{\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/thecamels.org\\\/\",\"https:\\\/\\\/x.com\\\/thecamelsorg\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/the-camels\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC01xYBZbIAApTuPWuqgGE4Q\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/thecamels.org\\\/en\\\/#\\\/schema\\\/person\\\/b7bd2aec5f506a68323eb40c86d38a32\",\"name\":\"Kamil Porembi\u0144ski\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g\",\"caption\":\"Kamil Porembi\u0144ski\"},\"description\":\"Architekt systemowy, administrator Linux, a czasem Windows. Lubi tematyk\u0119 security. Obecnie w\u0142a\u015bciciel firmy thecamels.org, zajmuj\u0105cej si\u0119 projektowaniem system\u00f3w o wysokiej dost\u0119pno\u015bci. Zajmuje si\u0119 skalowaniem du\u017cych aplikacji internetowych, wspieraniem startup\u00f3w w kwestiach serwerowych. Po godzinach zajmuje si\u0119 \u017ceglowaniem po morzach, lataniem, fotografi\u0105 i podr\u00f3\u017cami.\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The twelve-factor app - Thecamels.org","description":"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/","og_locale":"en_US","og_type":"article","og_title":"The twelve-factor app - Thecamels.org","og_description":"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.","og_url":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/?utm_source=dark&utm_medium=social&utm_campaign=open-graph","og_site_name":"Thecamels.org","article_publisher":"https:\/\/www.facebook.com\/thecamels.org\/","article_published_time":"2016-02-12T13:04:00+00:00","article_modified_time":"2021-01-13T07:13:31+00:00","og_image":[{"width":1200,"height":627,"url":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/17.png","type":"image\/png"}],"author":"Kamil Porembi\u0144ski","twitter_card":"summary_large_image","twitter_image":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/17.png","twitter_creator":"@thecamelsorg","twitter_site":"@thecamelsorg","twitter_misc":{"Written by":"Kamil Porembi\u0144ski","Est. reading time":"24 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#article","isPartOf":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/"},"author":{"name":"Kamil Porembi\u0144ski","@id":"https:\/\/thecamels.org\/en\/#\/schema\/person\/b7bd2aec5f506a68323eb40c86d38a32"},"headline":"The twelve-factor app","datePublished":"2016-02-12T13:04:00+00:00","dateModified":"2021-01-13T07:13:31+00:00","mainEntityOfPage":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/"},"wordCount":4813,"publisher":{"@id":"https:\/\/thecamels.org\/en\/#organization"},"image":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#primaryimage"},"thumbnailUrl":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/18.png","keywords":["server administration"],"articleSection":["Blog"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/","url":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/","name":"The twelve-factor app - Thecamels.org","isPartOf":{"@id":"https:\/\/thecamels.org\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#primaryimage"},"image":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#primaryimage"},"thumbnailUrl":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/18.png","datePublished":"2016-02-12T13:04:00+00:00","dateModified":"2021-01-13T07:13:31+00:00","description":"Are you a developer and you design SaaS applications? Or maybe DevOps or Ops Enginer? Then it is necessary to know The twelve-factor app.","breadcrumb":{"@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thecamels.org\/en\/the-twelve-factor-app\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#primaryimage","url":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/18.png","contentUrl":"https:\/\/thecamels.org\/wp-content\/uploads\/2016\/02\/18.png","width":1200,"height":627,"caption":"The twelve-factor app - aplikacja dwunastu czynnik\u00f3w"},{"@type":"BreadcrumbList","@id":"https:\/\/thecamels.org\/en\/the-twelve-factor-app\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"[HOME]","item":"https:\/\/thecamels.org\/en\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/thecamels.org\/en\/blog\/"},{"@type":"ListItem","position":3,"name":"The twelve-factor app"}]},{"@type":"WebSite","@id":"https:\/\/thecamels.org\/en\/#website","url":"https:\/\/thecamels.org\/en\/","name":"Thecamels.org","description":"Hosting SSD NVMe z certyfikatem SSL i HTTP\/2. Administracja serwerami, skalowanie infrastruktury. Mamy g\u0142ow\u0119 do serwer\u00f3w i zadbamy o Twoj\u0105 stron\u0119 w sieci.","publisher":{"@id":"https:\/\/thecamels.org\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/thecamels.org\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/thecamels.org\/en\/#organization","name":"Thecamels","url":"https:\/\/thecamels.org\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/thecamels.org\/en\/#\/schema\/logo\/image\/","url":"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/09\/TC-logo-nowe.png","contentUrl":"https:\/\/thecamels.org\/wp-content\/uploads\/2018\/09\/TC-logo-nowe.png","width":826,"height":106,"caption":"Thecamels"},"image":{"@id":"https:\/\/thecamels.org\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/thecamels.org\/","https:\/\/x.com\/thecamelsorg","https:\/\/www.linkedin.com\/company\/the-camels","https:\/\/www.youtube.com\/channel\/UC01xYBZbIAApTuPWuqgGE4Q"]},{"@type":"Person","@id":"https:\/\/thecamels.org\/en\/#\/schema\/person\/b7bd2aec5f506a68323eb40c86d38a32","name":"Kamil Porembi\u0144ski","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4b2d40949e6453ecdd7663e9a61fac171f31810a28bdc5be0c4d7eca89f41571?s=96&d=identicon&r=g","caption":"Kamil Porembi\u0144ski"},"description":"Architekt systemowy, administrator Linux, a czasem Windows. Lubi tematyk\u0119 security. Obecnie w\u0142a\u015bciciel firmy thecamels.org, zajmuj\u0105cej si\u0119 projektowaniem system\u00f3w o wysokiej dost\u0119pno\u015bci. Zajmuje si\u0119 skalowaniem du\u017cych aplikacji internetowych, wspieraniem startup\u00f3w w kwestiach serwerowych. Po godzinach zajmuje si\u0119 \u017ceglowaniem po morzach, lataniem, fotografi\u0105 i podr\u00f3\u017cami."}]}},"_links":{"self":[{"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/posts\/9285","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/comments?post=9285"}],"version-history":[{"count":5,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/posts\/9285\/revisions"}],"predecessor-version":[{"id":12382,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/posts\/9285\/revisions\/12382"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/media\/17185"}],"wp:attachment":[{"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/media?parent=9285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/categories?post=9285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thecamels.org\/en\/wp-json\/wp\/v2\/tags?post=9285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}