It works on my laptop
Aisha builds an app. It works on her laptop. She puts it on the server. It breaks.
A package is missing. The password is wrong. The folder is not there.
Twelve habits, called the twelve factors, stop most of these problems. Today you learn the first six.
Key words
| Word | What it means | Example |
|---|---|---|
| Twelve-factor app | An app built with twelve good habits so it is easy to deploy and grow. | |
| Database | An organised store of data that programs can search and change. | |
| Version control | A tool that keeps every version of your files. | |
| Network | Computers joined together so they can send data to each other. | |
| Codebase | All the code of one app, kept in one repository. | |
| Repository | A store for code and its full history. | |
| Deploy | As a verb: put the app on a computer and start it. In the twelve factors it is also a noun: one running copy of the app, such as test or live. | |
| Dependency | A package your code needs to run. | flask |
| Configuration | Settings that change between deploys, such as passwords and web addresses. | |
| Environment variable | A setting stored outside the code, in the place where the app runs. | PORT=9000 |
| Backing service | A service your app uses over the network, such as a database or email. | |
| Stateless | A process that keeps nothing on itself between requests. |
The cells students fill in are left blank in this preview.
Six habits
Each factor is a short rule. It has a reason. Learn the reason and you can find the rule again.
Run the code below to see factor 3 at work: the configuration comes from outside the code.
Try it: a setting from outside
import os
# Read a setting. If there is none, use "Hello".
greeting = os.environ.get("GREETING", "Hello")
print(greeting, "world")
# The code does not change. Only the setting changes.
# A setting that is missing should give a clear error, not a guess.
Factors 1 to 6
| Factor | Rule in plain words | Why |
|---|---|---|
| 1 Codebase | One codebase in version control. Many deploys come from it | Test and live run the same code |
| 2 Dependencies | Write down every package you need. Keep them apart from other projects | A new machine installs the same things |
| 3 Config | Keep settings in the environment, not in the code | The same code runs anywhere. No passwords in the repository |
| 4 Backing services | Treat a database or email service as a plug you can swap by changing a setting | You can change database without changing code |
| 5 Build, release, run | Keep three stages apart: make the program, add the settings, then run it | You can go back to an old release if the new one is bad |
| 6 Processes | Run as stateless processes. Keep data in a database, not in the process | Any process can answer any request. One can die and nothing is lost |
The cells students fill in are left blank in this preview.
Never put a password in code
data-callouts.warning.label
Code goes into a repository, and many people can read it. A password in code is shared with everyone. Keep passwords in the environment, and never in version control.
Try it: swap a backing service
import os
class MemoryStore:
def __init__(self):
self.items = []
def save(self, item):
self.items.append(item)
def load(self):
return self.items
class LoudStore(MemoryStore):
def save(self, item):
print("Saving", item)
super().save(item)
# The setting picks the store. The rest of the code does not change.
name = os.environ.get("STORE", "memory")
store = LoudStore() if name == "loud" else MemoryStore()
store.save("tea")
print(store.load())
# Change "memory" to "loud" in the line that reads STORE and run again.
# A real app swaps a small database for a big one in the same way.
Try it: why processes must be stateless
class Process:
def __init__(self, name):
self.name = name
self.basket = [] # kept inside this process
def add(self, item):
self.basket.append(item)
def show(self):
print(self.name, "sees", self.basket)
one = Process("process 1")
two = Process("process 2")
one.add("tea")
one.show()
two.show() # the second process knows nothing
# Fix it: make one shared basket outside both processes.
# In a real app, that shared place is a database.
Which factor is broken?
Have a go
Which factor is broken?
6 questionsYour answers are marked here and are not kept. A college account keeps every student’s marks.