Docker Deployment in Flagsmith
A complete, beginner-friendly guide to running Flagsmith in containers: what Docker is, which pieces you need, how they connect, how to configure, secure, upgrade, back up, monitor and scale them, and how to avoid the mistakes that wake people at night.
Picture a new engineer on their first day. They are told, “Please set up our feature flag service on a test server.” In the old days, that meant installing a language runtime, matching library versions, configuring a web server, setting up a database and hoping nothing clashed with the other software on the machine. Two days later the service starts, but it behaves differently from the one on the staging server, and nobody can say why. The software was the same. The machines were not.
Containers were invented to end this kind of confusion. A container packs an application together with everything it needs to run, so it behaves the same on a laptop, on a test server and in production. Docker is the best-known tool for building and running containers. Flagsmith, the open-source feature flag and remote configuration service, is published as ready-made container images, which makes Docker the most common way to run it on your own infrastructure.
This guide assumes you know nothing. We explain every new word the first time it appears, use everyday comparisons, and then climb to the topics that experienced operators care about: configuration, databases, networking, security, upgrades, backups, monitoring, scaling and high availability. We deliberately avoid code and command listings. The goal is to build understanding that lasts, so you can read any current deployment instructions with confidence. Because image names, settings and defaults change between versions, always confirm exact details in the current Flagsmith documentation before you deploy.
1Why Run Flagsmith in Docker
Before learning how, let us understand why so many teams choose containers for their flag service.
The problem containers solve
Software depends on its surroundings: the operating system, the language runtime, the libraries and the settings. When those surroundings differ between machines, the same software behaves differently. Engineers call this the “works on my machine” problem. A container solves it by bundling the application and its surroundings into one sealed package, called an image, that runs the same way everywhere a container engine is available.
Think of shipping goods in standard steel shipping containers. Before them, every cargo was packed differently, and loading ships was slow and chaotic. Once everything fits in a standard box, any crane, truck or ship can move it without caring what is inside. A software container is that standard box. The contents may be a flag service today and a database tomorrow, but every machine knows how to carry the box.
What Flagsmith gains
Flagsmith is built from several parts: a web application programming interface, a dashboard that people use in their browsers, background workers and a database. Running these as containers gives you repeatable setups, fast starts and stops, easy upgrades by swapping one image for another, and simple scaling by running more copies. It also lets you test a new version in a throwaway environment that matches production.
When Docker is a good fit
Strong reasons to use Docker
- You want identical setups for development, staging and production.
- You plan to self-host and need a clear, repeatable recipe.
- Your team already runs other containers and has the tools for it.
- You want upgrades and rollbacks to be a matter of changing an image version.
- You may later move to an orchestrator that runs containers at scale.
Reasons to pause
- Nobody on the team has ever operated containers or databases.
- You only need a flag service for a small project and the hosted service would do.
- Strict rules forbid running container engines on your servers.
- You expect to spend no time on upgrades, backups and monitoring.
Docker makes the packaging easy. It does not make the operating easy. Backups, security, monitoring and upgrades are still your work, and the later chapters cover each one.
2Docker in Plain Words
If Docker has always sounded like jargon, this chapter turns it into a handful of simple ideas.
Image, container and registry
An image is a read-only template: a frozen snapshot of an application and everything it needs. A container is a running instance created from an image. You can start many containers from one image, just as you can bake many loaves from one recipe. A registry is an online library where images are stored and shared. Docker Hub is the best-known public registry, and Flagsmith publishes its images there. Companies also run private registries for their own images.
An image is a recipe card. A container is the dish cooked from it. A registry is the cookbook shelf where recipe cards are kept. You can cook the same dish in a hundred kitchens, and it will taste the same because the recipe fixed the ingredients and steps in advance.
Tags and versions
Every image in a registry has one or more tags, which are labels that usually indicate a version. A tag such as a version number points to a specific release. A tag such as latest points to whatever is newest at the moment. Latest is convenient for experiments but risky for production, because a restart could silently pull a different version than the one you tested. Careful teams pin an exact version and change it only on purpose.
Volumes: where data survives
A container’s own storage is temporary. When the container is removed, whatever was written inside disappears. A volume is storage kept outside the container so that data survives restarts and replacements. Databases need volumes, or an equivalent, because losing the database means losing every flag.
Networks and ports
Containers talk to each other over virtual networks created by Docker. A port is a numbered doorway on a container. By publishing a port, you connect a doorway on the container to a doorway on the host machine, so that outside traffic can reach it. Containers on the same private network can talk freely without publishing anything to the outside world, which is the safer way to connect an application to its database.
Environment variables
Containers are usually configured through environment variables, which are named settings passed in when the container starts. They let one image behave differently in each environment without rebuilding it. The database address, the secret key and the allowed web addresses are typical examples. Because some settings are secrets, how you store and pass them matters a great deal.
Compose and orchestrators
Running several containers by hand is tedious. Docker Compose lets you describe a group of containers, their networks, their volumes and their settings in one file and start everything together. For larger deployments, an orchestrator such as Kubernetes or a managed container service on a cloud platform runs containers across many machines, restarts failed ones and balances traffic. The ideas in this guide apply to all of them, even though the tools differ.
Image
A frozen, read-only package containing an application and everything it needs to run.
Container
A live instance started from an image, which can be stopped, replaced or multiplied.
Registry
An online store of images, public or private, from which machines download what they need.
Tag
A name, often a version number, that points to a particular build of an image.
Volume
Storage kept outside a container so data survives restarts and replacement.
Environment variable
A named setting passed to a container at start, letting one image serve many environments.
3Flagsmith Components You Will Containerise
A Flagsmith installation is a small family of cooperating parts. Knowing each member makes every later decision easier.
The API
The API is the heart of Flagsmith. It receives questions from SDKs, such as “what is the value of this flag for this user?”, and requests from the dashboard and automation, such as “create a new flag.” It reads and writes the database, applies targeting rules and returns answers. It is written as a web application, and it listens on a network port inside its container.
The dashboard
The dashboard is the web page where people manage flags. In the common all-in-one image, the dashboard and the API are packaged together, which makes small deployments simple. Flagsmith has also published separate images for the API and the dashboard for teams who prefer to run and scale them independently. Which images exist and how they are combined can change, so confirm the current options in the documentation.
The database
The database is the permanent memory of the system. It holds organisations, projects, environments, features, segments, users, permissions and the audit log. Flagsmith is commonly run with the PostgreSQL database. A container engine can run a database container for tests and small setups, but production teams often prefer a managed database service or a carefully operated database server, because the database is the one part you can never afford to lose.
The background worker
Some work should not happen while a person waits, such as sending webhooks, writing audit entries and processing analytics. Flagsmith can hand this work to a background processor. In small setups the application handles these jobs itself. In larger ones, you run a dedicated task processor as a separate container so heavy background work never slows down the part that answers flag questions.
The cache and the edge proxy
Two optional parts can improve speed. A cache holds ready answers so the database is asked less often. An edge proxy is a lightweight service that sits near your applications, keeps a copy of the flag data and answers SDK questions quickly, reducing load on the main installation. Flagsmith publishes an edge proxy for this purpose, and it is worth knowing about even if you start without it.
Think of a library. The API is the librarian who answers questions at the desk. The dashboard is the catalogue room where staff organise the shelves. The database is the collection of books, which must never be lost. The background worker is the back-office team who send out reminders and file paperwork. The edge proxy is a small branch library that keeps popular books close to readers so the main library is not overwhelmed.
| Part | Job | Needs permanent storage? | Can run several copies? |
|---|---|---|---|
| API | Answers flag questions and handles management | No, it keeps nothing itself | Yes, behind a load balancer |
| Dashboard | Gives people a web interface | No | Yes |
| Database | Stores everything permanently | Yes, essential | Needs a deliberate design for copies |
| Task processor | Runs background jobs | No | Yes, to match the workload |
| Cache | Holds fast temporary answers | Not for correctness | Depends on the cache technology |
| Edge proxy | Serves flags near your applications | No | Yes |
The word stateless describes a part that remembers nothing between requests, so any copy can answer any request. The API and dashboard are largely stateless, which is why they are easy to multiply. The database is the stateful part, which is why it needs the most care.
4Choosing Images and Versions
Which image you pull, and which version you pin, is one of the quietest and most important decisions in the whole deployment.
Official images
Flagsmith publishes official images in public registries under its own organisation name. The main image bundles the API and dashboard together, which is the easiest way to start. Other images cover the separate dashboard, the task processor and the edge proxy. Always take images from the official publisher and verify the name carefully, because look-alike images with similar names can exist in public registries.
Pinning versions
For anything beyond a quick experiment, pin a specific version tag instead of using latest. Pinning gives you three benefits. You know exactly what is running. You can reproduce the setup on another machine. And you control when an upgrade happens, because nothing changes until you change the tag. A reasonable routine is to read the release notes, test the new version in a staging environment and only then update the pinned tag in production.
Image digests
Tags can be moved by the publisher. A digest is a long fingerprint that identifies one exact image forever. Security-conscious teams sometimes pin by digest for the strictest guarantee, or copy approved images into their own private registry so that production never depends on a public service being available at deploy time.
A tag is like the label “today’s special” on a menu: it can point to a different dish tomorrow. A digest is like the exact photograph of the dish. If you want the very same meal every time, you order by the photograph.
Private registries and mirroring
Many companies keep a copy of each approved image in a private registry inside their own cloud account. This protects against a public registry being slow, rate limited or unreachable, lets security teams scan every image before it is used, and ensures the exact bytes you tested are the bytes you run. The small extra effort of mirroring pays for itself the first time a public service has a bad day.
Never let production pull “latest” automatically. A restart at the wrong moment could bring up a newer version with changes you have not tested, including database changes that cannot be undone easily.
Pick the official image
Confirm the publisher and the exact image names in the current documentation.
Choose a specific version
Select a released version tag, not latest, and write it down in your configuration.
Scan and mirror
Scan the image for known weaknesses and copy it into your private registry.
Test in staging
Run it with a copy of realistic data and confirm that everything works.
Promote to production
Use the same tag in production so that what you tested is what you run.
5The Deployment Architecture
A picture of the whole system shows how the containers, the database and the outside world fit together.
flowchart TB
U["Users and Dashboard Browsers"] --> P["Reverse Proxy with TLS"]
S["Application SDKs"] --> P
P --> A1["Flagsmith Container 1"]
P --> A2["Flagsmith Container 2"]
A1 --> DB[("PostgreSQL Database")]
A2 --> DB
T["Task Processor Container"] --> DB
A1 --> Q["Task Queue in Database"]
A2 --> Q
Q --> T
T --> W["Outbound Webhooks"]
DB --> B["Scheduled Backups"]
M["Monitoring and Logs"] -.-> A1
M -.-> A2
M -.-> T
M -.-> DB
Walking through the diagram
Traffic enters at the top. People using the dashboard and applications using SDKs both reach a reverse proxy, which is a front door that accepts connections, handles encryption and passes requests along. Behind it, two copies of the Flagsmith container share the work. Both copies talk to the same database, which is the single source of truth. A separate task processor container takes over background jobs, such as sending webhooks to outside services. Backups of the database run on a schedule, and monitoring watches every part.
The dotted lines for monitoring show that observation is not part of the request path. It watches quietly and raises alarms. The solid lines show the path real requests and data take. Notice that only the proxy is exposed to the outside world. The application containers, the task processor and the database sit on private networks where outsiders cannot reach them directly.
The deployment is like a hotel. Guests enter through a reception desk, which is the reverse proxy. Behind it, several receptionists, the application containers, handle requests. A back-office team, the task processor, does paperwork away from the guests. The vault in the basement, the database, holds the valuables and only staff can reach it. Security cameras, the monitoring, watch everything without getting in anyone’s way.
The pieces in plain words
Reverse proxy
Accepts outside connections, handles encryption certificates and forwards requests to the right container.
Application containers
Several identical copies of Flagsmith that answer flag questions and serve the dashboard.
Database
The permanent store of all configuration and history. Protected by backups and kept off the public internet.
Task processor
Runs background jobs separately so the main containers stay quick.
Backups
Scheduled copies of the database stored in a separate place, so a disaster is survivable.
Monitoring and logs
Measurements and records that show how healthy the system is and what happened when it was not.
6What Happens When the Containers Start
A start-up sequence that works the same way every time is a sign of a healthy deployment. Let us follow it step by step.
sequenceDiagram
participant O as Operator or Orchestrator
participant D as Database
participant A as Flagsmith Container
participant T as Task Processor
participant P as Reverse Proxy
O->>D: Start database and wait until healthy
O->>A: Start application with settings
A->>D: Connect and check schema version
alt Database needs updates
A->>D: Apply database migrations
else Already up to date
A->>A: Continue start up
end
A->>A: Report healthy on health check
O->>T: Start task processor
T->>D: Connect and begin polling for jobs
O->>P: Start or update proxy routes
P->>A: Send test request
A-->>P: Healthy response
P-->>O: Ready to receive traffic
Reading the sequence
The order matters. The database must be running and healthy before the application starts, because the application needs it immediately. When the application starts, it connects to the database and checks whether the structure of the stored data matches what this version of the software expects. If the structure is out of date, the application applies migrations, which are scripted changes that bring the database structure up to date. Once that is done, the application reports that it is healthy.
The task processor starts next, connects to the same database and begins looking for background jobs. Finally, the reverse proxy sends a test request, receives a healthy answer and begins forwarding real traffic. Orchestrators automate this order through health checks and dependency rules, so no human has to watch the sequence.
Why migrations deserve respect
A migration changes the shape of your most precious data. Most are quick and safe, but some can take time on large tables, and once applied they usually cannot be reversed by simply starting an older image. This is why upgrades must always be preceded by a backup, and why running several new containers at the same instant, each trying to migrate the same database, needs care. Many teams run the migration step once, in a controlled way, before bringing up the new application copies.
A migration is like renovating a warehouse’s shelving while the goods are still inside. If you do it carefully, with a plan and a photograph of the old layout, nothing is lost. If five crews start rearranging the same shelves at once without talking to each other, you end up with a mess.
Define a health check for every container, so that the orchestrator knows when a container is truly ready and not merely started. A container that is running but not ready should receive no traffic.
7Configuration and Environment Settings
The same image behaves differently in each place because of the settings you give it. Getting these right is most of the work.
The kinds of settings
Flagsmith containers are configured mainly through environment variables. You can think of the settings as belonging to a few families. Database settings tell the application where its data lives and how to log in. Security settings include a secret key used to protect sessions and signed data, and a list of web addresses the application is allowed to answer to. Behaviour settings control things like whether registration is open, how background tasks run and how much logging to produce. Integration settings configure email delivery, single sign-on and connections to other services.
The database address
The most important setting is the location and credentials of the database. This is typically given as a single connection address containing the host, port, database name, user and password. Because it contains a password, treat it as a secret. Test it from inside the same network as the container, since a database that is reachable from your laptop may not be reachable from the container.
The secret key
The secret key is a long random value that the application uses to protect login sessions and signed information. It must be unique for each installation, generated with a secure random generator, and kept stable. If you change it casually, existing sessions stop working. If you leak it, an attacker may be able to forge signed data. Never reuse the example value from a tutorial.
Allowed hosts and web addresses
Web applications protect themselves by accepting requests only for web addresses they expect. You tell Flagsmith which hostnames it should answer to. A common cause of mysterious errors on a new deployment is that the address people type into their browser is missing from this list. Similar settings tell the dashboard where the API lives and how links in emails should be built, so a wrong public address leads to broken links.
Environment settings are like the settings on a rented flat’s keypad lock and mailbox. The building is the same for everyone, but your door code, your name on the mailbox and the list of visitors you allow are yours alone. If the visitor list does not include your friend’s name, the doorman turns them away, however friendly they look.
Where to keep settings
An environment file
A file next to your container definition holds the settings. Easy for small setups, but the file must be protected and never committed to shared code storage.
Container secrets
Docker and orchestrators can store sensitive values separately and present them to containers safely at start.
A secrets manager
A dedicated service stores, rotates and audits access to secrets, and injects them when containers start.
Baking into images
Putting secrets inside an image means anyone who can pull the image can read them. Never do this.
Setting names and defaults evolve between releases. Copy names only from the documentation for the exact version you are running, and be cautious with old blog posts and forum answers.
| Setting family | What it controls | Typical care needed |
|---|---|---|
| Database connection | Where data lives and how to log in | Treat as secret, test from inside the network |
| Secret key | Protection of sessions and signed data | Unique, random, stable, never shared |
| Allowed hosts | Which web addresses the app answers to | Must include the public address users type |
| Public addresses | How links and the dashboard find the API | Must match the real public web address |
| Email settings | How invitations and resets are sent | Use a trusted mail service, protect credentials |
| Sign-on settings | Login through a company identity service | Check edition support and test with a spare account |
| Background task mode | Whether jobs run in the app or a worker | Match to your load and your design |
| Logging level | How much detail is written | Balance usefulness with storage and privacy |
8The Database Strategy
If you remember only one chapter, make it this one. Containers can be replaced in seconds, but the database holds everything you cannot afford to lose.
Containerised database or managed service?
You have two broad options. You can run the database as a container next to Flagsmith, which is simple and perfect for development, demonstrations and small internal tools. Or you can use a database that runs outside your container setup: a managed database service from a cloud provider, or a database server your operations team already maintains. For production, the second option is usually wiser, because those services provide automated backups, replication, patching and failover that you would otherwise build yourself.
Database in a container
- Fast to start and easy to throw away for tests.
- Everything is described in one place.
- No extra cost or accounts needed.
- Good for development and small, low-risk uses.
Risks in production
- You must build backups, failover and patching yourself.
- A careless cleanup command can destroy the data volume.
- Storage performance depends on the host machine.
- Recovery depends on skills your team may not have.
Sizing and growth
Flagsmith’s data is small compared with many applications, because flags and configuration are modest in size. The audit log and analytics data can grow steadily over time, so plan for storage growth and watch disk space. The database also handles the reads that happen when SDKs ask for flag values, which is why caching and local evaluation in SDKs help so much. Start with a modest instance, measure, and grow it when the numbers say so.
Connections
Every application container opens connections to the database, and a database can only handle so many at once. If you run many copies of the application, the total number of connections multiplies. Teams use connection pooling, a small service that shares a limited number of database connections among many clients, when they scale out. Keep an eye on the number of open connections as you add containers.
Protecting the database
- Place it on a private network, reachable only from the application and task processor containers.
- Use a strong, unique password and a dedicated database user with only the rights Flagsmith needs.
- Enable encryption of connections and of stored data where the platform offers it.
- Keep the database software patched on a regular schedule.
- Separate production and non-production databases completely.
The containers are like the staff of a shop, who can be replaced at any time. The database is the shop’s accounts book and stock record. You can hire new staff in minutes, but if the accounts book burns, the shop’s memory is gone. So you keep copies of the book in a fireproof safe somewhere else.
If you start with a containerised database, write down now when and how you will move to a managed one. Moving early, while the data is small, is far easier than moving under pressure later.
9Networking, Ports and the Reverse Proxy
Containers are shy by default. This chapter explains how to let the right visitors in and keep everyone else out.
Container networks
Docker creates private virtual networks for containers. Containers on the same network can find each other by name, so the application can reach the database by using the database container’s name as its address. Containers on different networks cannot talk unless you connect them. A sensible design uses at least two networks: a front network shared by the proxy and the application, and a back network shared by the application, the task processor and the database. The database is then invisible to the proxy and to the outside world.
Publishing ports
A container’s port is unreachable from the outside until you publish it. Flagsmith’s application listens on a port inside its container. In a well-designed setup, you publish only the proxy’s ports, usually the standard secure web port, and leave everything else unpublished. A frequent beginner mistake is to publish the database port to the whole world for convenience, which invites attacks within hours.
The reverse proxy
A reverse proxy sits in front of your application and does several jobs. It terminates TLS, meaning it handles the encryption certificates so that traffic between users and your service is protected. It forwards requests to healthy application containers and spreads the load among them. It can add security headers, limit request sizes, enforce rate limits and write access logs. Common choices include widely used web servers and dedicated proxies, as well as the load balancers offered by cloud platforms.
The reverse proxy is the receptionist of an office building. Visitors never wander the corridors. They speak to the receptionist, who checks who they are, tells them where to go and keeps a visitor log. The offices behind the desk do not need to deal with strangers directly.
Certificates and HTTPS
Always serve Flagsmith over HTTPS. A certificate proves that your server is the one it claims to be and enables encryption. Many teams obtain free certificates from automated certificate authorities and let the proxy renew them on a schedule. Expired certificates are one of the most common causes of sudden outages, so monitor their expiry dates and alert well before they lapse.
Addresses that must agree
Several places need to agree on the public web address: the proxy, the allowed hosts setting in Flagsmith, the setting that tells the dashboard where the API lives, and the address configured in every SDK. When something fails strangely after a change of domain name, the first thing to check is whether all of these still match.
| Network element | Exposed to the internet? | Why |
|---|---|---|
| Reverse proxy secure port | Yes | It is the only intended public door |
| Redirect from plain to secure web port | Yes, redirect only | Sends visitors to the encrypted address |
| Application container port | No | Reached only through the proxy |
| Task processor | No | Has no need for inbound traffic |
| Database port | Never | Reached only by the application and task processor |
| Monitoring dashboards | Only for staff, behind sign-in | Contain sensitive operational detail |
Docker can modify firewall rules automatically when ports are published, which sometimes bypasses firewalls that administrators thought were protecting them. Test from outside your network to confirm that only the ports you intend are reachable.
10Storage, Volumes and Persistence
Containers forget everything when they are replaced. Storage is the plan for what must be remembered.
What must persist
Almost everything that matters in a Flagsmith deployment lives in the database. The application containers themselves are meant to be disposable: you can destroy and recreate them at any time without losing anything. So the question of persistence mostly means “how do we protect the database’s files?” Other items worth keeping include your configuration files, your certificates and any exported backups.
Types of storage
Named volumes
Storage managed by the container engine. Simple, portable and suited to single-host setups.
Bind mounts
A folder on the host machine made visible inside the container. Easy to inspect, but ties the container to that machine.
Network or block storage
Storage provided by the platform that can move between machines and be snapshotted.
Managed database storage
The database service handles disks, replication and snapshots on your behalf.
Performance and safety of disks
Databases need fast, reliable disks. Slow or shared disks cause slow responses that look like application problems. Put the data on storage with predictable performance, keep generous free space and monitor usage. A database that fills its disk usually stops accepting writes, which stops Flagsmith from saving any change.
Protecting against accidents
The most common cause of data loss in container setups is not a hacker but a person, running a cleanup action that removes volumes along with containers. Protect against this with clear naming, restricted permissions, separate volumes for production and test, and, above all, tested backups. Treat any instruction that says “remove everything including volumes” with great suspicion.
Volumes are like the safe deposit boxes in a bank, while containers are the temporary desks in the lobby. Desks can be cleared and swapped every day. The safe deposit boxes are where the valuables live, so they sit in a vault with careful access rules and a record of who opened them.
Moving the database off the container host, to a managed service, removes the whole category of volume mistakes. This is one of the strongest arguments for managed databases in production.
11A Single-Host Deployment with Compose
The simplest useful deployment runs everything on one machine. Here is how to think about it, without a single line of code.
What a Compose description contains
A Compose description is a single file that lists the services you want, such as the proxy, the Flagsmith application, the task processor and the database. For each service it states which image and version to use, which settings to pass, which networks to join, which volumes to attach and which ports to publish. It also states dependencies and health checks, so that the database starts first and the application waits for it. With this one file, an entire environment can be started, stopped and recreated with a single instruction.
When single-host is enough
A single host suits development environments, demonstrations, internal tools, small teams and low-risk production uses where a short outage is acceptable. It is easy to understand, easy to back up and cheap. Its limitation is obvious: if the machine fails, everything fails. For anything critical, you will want more than one copy of the application on more than one machine, and a database that can survive failure.
Good habits for a single host
Pin every version
List exact image versions for Flagsmith, the proxy and the database. Never rely on latest.
Keep secrets out of the file
Reference a protected settings file or secret store instead of typing passwords into the main description.
Define restart behaviour
Tell the engine to restart containers after failures and after the machine reboots.
Add health checks
Make each service report when it is truly ready, so dependent services wait correctly.
Back up outside the host
Copy database backups to a different machine or storage service, since the host itself may be the thing that fails.
Store the description in version control
Keep the file in a protected repository so changes are reviewed and can be rolled back.
A Compose description is like a stage manager’s plan for a play. It lists the actors, where each one stands, who enters first and what props they carry. Anyone can take the plan, set up the stage in a new theatre and run the same show.
Treat a single-host deployment as a first step, not a final destination. Writing the setup cleanly from the start makes the later move to several hosts or an orchestrator much easier.
12The Task Processor and Background Work
Some jobs should happen quietly in the background. The task processor is the part of the system that does them.
What background work exists
Flagsmith performs several jobs that do not need to finish before a request returns. It sends webhooks to your outside services when flags change. It records audit entries. It processes usage and analytics data. It sends emails. If all of this happened while a person or an SDK waited, every request would be slower and a slow external service could drag everything down.
Two ways to run it
In a simple setup, the application containers process background jobs themselves, in the background of their own processes. This is easy and sufficient for light use. In a larger setup, you run a dedicated task processor as its own container, using the same image started in a different mode. The application then places jobs on a queue stored in the database, and the task processor picks them up. This separates concerns: the web-facing containers stay fast, and the background container can be scaled according to the backlog of work.
Think of a restaurant. Waiters take orders and serve food at the tables, and the kitchen cooks. If the waiters also had to cook, service would slow down whenever the kitchen got busy. A dedicated task processor is the kitchen: the front of house stays responsive while the heavy work happens behind the doors.
What to watch
- The size of the job backlog, because a growing backlog means workers cannot keep up.
- The age of the oldest waiting job, which tells you how late your webhooks and records are.
- Failure counts, because repeated failures suggest a broken external service or a bad configuration.
- Network permissions, because the task processor, not the web container, is the one that calls outward to your webhook receivers.
| Mode | Good for | Watch out for |
|---|---|---|
| Background work inside application containers | Small and light installations | Bursts of jobs competing with request handling |
| Dedicated task processor container | Production setups with webhooks, audits and analytics | Remembering to monitor it and to allow its outbound traffic |
| Several task processors | Heavy background workloads | Database connections and contention |
A stopped task processor is a silent failure: the dashboard still works, flags still evaluate, but webhooks stop and audit processing falls behind. Always include the task processor in your monitoring and alerts.
13Security Hardening
A flag service can change what your product does within seconds, so protecting it deserves real effort. Here are the layers that matter.
Secure the image
Start with what you run. Pull images only from the official publisher, pin versions, and scan images for known weaknesses before they reach production. Keep a private copy in your own registry and rebuild or update regularly, because images contain operating system components that receive security fixes over time. Remove any image you no longer use.
Run containers with minimal power
Containers should not have more rights than they need. Prefer running processes as an ordinary user instead of the all-powerful administrator account. Make the container’s file system read-only where possible, so an intruder cannot easily modify the software. Drop unneeded capabilities and avoid privileged mode, which gives a container nearly the same power as the host. Never mount the container engine’s control socket into an application container, since that is equivalent to handing over the keys to the whole machine.
Secure the network
Expose only the reverse proxy. Keep the database and workers on private networks. Use a firewall at the host or cloud level as a second layer, and test from outside to verify. Restrict who can reach administrative tools and monitoring dashboards. Where your applications run in the same cloud network, consider keeping SDK traffic on private paths and not on the public internet.
Secure the secrets
Store passwords, keys and tokens in a secrets manager or the secret facilities of your orchestrator. Use different secrets for each environment. Rotate them on a schedule and immediately after any suspected exposure. Never place secrets in images, in shared documents or in chat messages, and take care that logs do not print them.
Secure the people
The Flagsmith dashboard has its own users and roles. Give each person an individual account, use the principle of least privilege so that only a few people can change production, and use single sign-on and multi-factor authentication where your edition supports them. Review the list of users regularly and remove people who have left. Protect the keys that automation uses to call the management interface with the same care as passwords.
Hardening is like securing a house with layers. A fence keeps casual visitors away, a locked door stops the curious, a safe holds the valuables and an alarm tells you when something is wrong. No single layer is perfect, but together they make a burglar’s job slow and noisy.
Do
- Pin and scan images, and mirror them to a private registry.
- Run as a normal user with a read-only file system where possible.
- Expose only the proxy, over HTTPS.
- Keep secrets in a manager and rotate them.
- Use individual accounts, roles and multi-factor authentication.
Do not
- Run privileged containers or mount the engine’s control socket.
- Publish the database port to the internet.
- Bake passwords into images or commit them to code storage.
- Share one administrator account among the whole team.
- Ignore security fixes for months.
Send only what you need to Flagsmith. Using opaque user identifiers and a minimal set of traits reduces privacy risk and makes security reviews far easier.
14Upgrades and Rollbacks
Upgrading is where container setups shine and where careless teams get hurt. A calm routine makes it boring, which is exactly what you want.
flowchart TD
A["Read release notes for the new version"] --> B["Back up the database and verify the backup"]
B --> C["Deploy the new version in staging with a copy of data"]
C --> D{"Staging checks pass"}
D -- No --> E["Stop and investigate or wait for a fix"]
D -- Yes --> F["Schedule a quiet window for production"]
F --> G["Run database migrations once in a controlled step"]
G --> H["Replace application containers gradually"]
H --> I["Replace task processor"]
I --> J{"Health and errors normal"}
J -- Yes --> K["Finish and record the version"]
J -- No --> L["Roll back images and restore data if needed"]
Reading the flow
The path begins with reading, because release notes tell you about changes that need attention, such as new settings, removed features or heavy migrations. Next comes a backup, and a verified one, since a backup that cannot be restored gives false comfort. The new version is then tried in staging against a copy of realistic data. Only if staging looks healthy do you choose a quiet time for production.
In production, the database migration runs once in a controlled step. Then the application containers are replaced gradually, so some old and some new copies handle traffic during the changeover, and finally the task processor is updated. If health checks and error rates look normal, the upgrade is complete and recorded. If not, you roll back.
Understanding rollbacks
Rolling back containers is easy: you point back to the previous image version and restart. Rolling back the database is not always easy. If the new version changed the structure of the data in a way the old version cannot read, the old containers may fail against the migrated database. This is why a backup taken just before the upgrade is the real rollback tool: restoring it returns both the data and its structure to the earlier state, at the cost of any changes made since. Some releases are designed to be compatible with the previous version for a time, and the release notes tell you when that applies.
Upgrading is like replacing the engine of a bus while passengers wait at the next stop. You read the manual, take a photograph of the old setup, practise on a spare bus first, and swap the parts in a quiet hour. If the new engine misbehaves, you can fit the old one back, but only if you kept it and the passengers’ luggage was not rearranged in between.
Rolling updates and zero downtime
When you run more than one application container behind a proxy, you can replace them one at a time, letting the others serve traffic. This is called a rolling update. Combined with health checks, it allows upgrades with little or no visible interruption. It works best when the new and old versions can safely share the same database for the short overlap, which is a question for the release notes.
Skipping many versions at once makes upgrades riskier. Upgrade in regular, modest steps, and follow any special instructions in release notes when a version requires an intermediate stop.
15Backups and Disaster Recovery
A backup you have never restored is only a hope. This chapter turns hope into a plan.
What to back up
The database is the essential item, because it contains every flag, segment, user and audit entry. Also keep your deployment description, your settings with secrets stored safely elsewhere, your certificates or the means to reissue them, and records of which image versions you run. With these, you can rebuild everything else from scratch.
Types of database backup
A logical backup exports the data as a portable set of instructions and is simple, flexible and good for moving between versions or machines. A physical or snapshot backup copies the underlying storage and is quicker for large databases and for restoring to the same kind of system. Many teams use both: regular snapshots for fast recovery and periodic logical exports as an independent safety net. Managed database services typically provide automated snapshots and point-in-time recovery, which lets you restore to a chosen moment.
Two numbers that matter
Recovery point objective is how much recent data you can afford to lose, measured in time. If it is fifteen minutes, backups or log shipping must capture changes at least that often. Recovery time objective is how long you can afford to be down while restoring. If it is one hour, your restoration process must be rehearsed and fast enough to meet that. Write these numbers down, because they decide your backup design and its cost.
Backups are like keeping copies of important papers. A photocopy in the same drawer helps if you spill coffee on the original, but not if the house burns down. Keeping a copy at a relative’s home is a better plan. And knowing where the copy is, and how to fetch it quickly, is as important as having it.
Rehearse the restore
Pick a backup
Choose a recent backup from storage, not from the same machine that hosts the live database.
Restore into a clean environment
Create a fresh, isolated database and restore into it, never over production.
Start Flagsmith against it
Bring up the same image version against the restored database and watch for errors.
Verify the content
Check that projects, flags, segments and recent audit entries are present and correct.
Record the time taken
Write down how long it took and what surprised you, then compare with your recovery time target.
Protecting the backups themselves
Backups contain everything that the live database does, so they need the same security. Encrypt them, restrict who can read them, store them in a separate account or location and keep several generations. Consider making some copies immutable, meaning they cannot be altered or deleted for a period, to protect against mistakes and malicious deletion.
Even if you trust your database backups completely, keep a periodic export of your flag configuration through Flagsmith’s own interfaces. It gives you an independent, human-readable record that can help rebuild a setup or migrate elsewhere.
16Health Checks, Logging and Monitoring
You cannot fix what you cannot see. Good observation turns surprises into scheduled work.
Health checks
A health check is a small test that tells the container engine or orchestrator whether a container is working. Flagsmith provides a simple health endpoint that returns a success answer when the application is running. Configure your orchestrator to call it regularly. A failing check can cause the platform to restart the container or stop sending it traffic. Distinguish between a liveness check, which asks “is the process alive?”, and a readiness check, which asks “is it ready to serve requests?”, since a container may be alive but still starting.
Logs
Containers write logs to their standard output, and the engine collects them. In production, send logs to a central place, so that they survive container replacement and can be searched across all copies. Include a clear timestamp, the container name and the severity level. Protect logs from containing secrets or sensitive user data, and decide how long to keep them. Logs are the first thing you read in an incident.
Metrics
Metrics are numbers measured over time. Flagsmith can expose operational metrics that common monitoring tools collect, and you can add measurements from the host, the containers, the proxy and the database. A small set of signals tells most of the story.
| Signal | What it reveals | Alert idea |
|---|---|---|
| Request rate | How much traffic Flagsmith serves | Alert on a sudden drop to near zero or a sharp rise |
| Error rate | Whether requests are failing | Alert when the share of errors passes a small threshold |
| Response time | How quickly answers return | Alert when the slow tail grows |
| Container restarts | Crashes or memory problems | Alert on repeated restarts |
| Memory and CPU | Whether containers have enough resources | Alert when usage stays near the limit |
| Database connections | Pressure on the database | Alert as the count nears the maximum |
| Database disk space | Whether storage will run out | Alert well before the disk is full |
| Task backlog and age | Whether background work keeps up | Alert if the oldest job waits too long |
| Certificate expiry | Whether HTTPS will break soon | Alert weeks ahead |
| Backup success | Whether recovery is possible | Alert on any missed or failed backup |
Monitoring is the dashboard of a car. The fuel gauge, temperature light and speedometer do not drive the car, but they let you notice a problem long before the engine stops on the motorway. You do not wait for smoke to learn that the radiator is overheating.
Alerts that people trust
Alerts should be few, clear and actionable. If an alert fires often and needs no action, people learn to ignore it, and the one real emergency gets lost. Each alert should say what is wrong, why it matters and what to try first. Route urgent ones to a person on call, and send less urgent ones to a daily review.
Alert on silence as well as errors. If the number of requests suddenly drops to zero, something upstream may be broken even if no error messages appear.
17Scaling and Orchestrators
When one machine is no longer enough, containers make it natural to grow. Here is how the pieces scale and what tools help.
Scaling the application
The Flagsmith application containers are largely stateless, so scaling them is simple: run more copies behind the proxy or load balancer. Each copy opens connections to the database, so more copies mean more connections, which is the first limit most teams meet. Use connection pooling when the count grows. Set resource limits for memory and processor use on each container, so a misbehaving copy cannot starve its neighbours.
Scaling the database
The database is harder to scale because it holds the state. The usual path is to grow the instance first, then add read replicas to share read traffic, tune indexes and caching, and reduce the load by using smart SDK behaviour. Because the volume of flag changes is small compared with the volume of flag reads, read scaling is more important than write scaling.
Scaling the background work
Add task processor containers when the backlog of jobs keeps growing. Watch for contention on the database as more workers compete for jobs, and tune the number of workers to the work rather than simply adding more.
Orchestrators
An orchestrator is a system that runs containers across many machines, restarts failed ones, balances traffic and performs rolling updates automatically. Kubernetes is the most widely used. Cloud platforms also offer managed container services that hide much of the machinery. Flagsmith provides guidance and packaging for popular orchestrators, which you should read in the current documentation. Orchestrators add power and complexity, so adopt one only when your needs justify it.
An orchestrator is like an airport operations centre. Individual planes are the containers. The centre decides which gate each uses, replaces a plane that has a fault, spreads passengers across flights and keeps the schedule moving. A small airfield with two planes can be run by a single person with a clipboard, and does not need such a centre.
Single host with Compose
Simple and cheap. Suits development and small production uses that tolerate short outages.
Managed container service
A cloud service that runs your containers without you managing the machines. A good middle path.
Kubernetes
A powerful orchestrator for larger teams that already operate it and need fine control.
Virtual machines plus containers
A few machines each running containers behind a load balancer, with scripts for deployment.
Reduce the load before you scale the system. Local evaluation and caching in your SDKs can cut the number of requests to Flagsmith dramatically, which often delays or removes the need for a bigger deployment.
18Designing for High Availability
High availability means the service keeps working when parts fail. It is a design, not a switch.
flowchart TB
LB["Load Balancer across Zones"] --> A1["App Container Zone A"]
LB --> A2["App Container Zone B"]
LB --> A3["App Container Zone C"]
A1 --> PG["Database Primary Zone A"]
A2 --> PG
A3 --> PG
PG --> R1["Standby Replica Zone B"]
PG --> R2["Read Replica Zone C"]
T1["Task Processor Zone A"] --> PG
T2["Task Processor Zone B"] --> PG
PG --> BK["Backups to Separate Account"]
R1 -. "Automatic failover" .-> PG
Reading the design
The load balancer sits across several availability zones, which are separate data centre areas within a region with independent power and networking. Three application containers, one in each zone, serve traffic, so the loss of an entire zone leaves two still working. Two task processors, in different zones, make sure background work continues. The database has a primary in one zone and a standby in another that can take over automatically if the primary fails. A read replica shares read traffic. Backups go to a separate account, so even a serious mistake in the main account cannot destroy every copy.
The weakest link
The chain is only as strong as its weakest link. A beautiful application layer on top of a single database server is not highly available. Check each part of the chain: load balancer, application, database, storage, network, certificates, secrets and the deployment process itself. Ask of each, “what happens if this fails right now?” and write the answer down.
High availability is like a hospital with backup generators, spare surgeons on call and two separate entrances. It is not enough to have a spare for the most obvious part. The lights, the water, the doors and the staff rota all need a plan for the day they fail.
Do not forget the client side
No design is perfect, so your applications should also protect themselves. Set safe default values in code, let SDKs keep recent answers in memory, prefer local evaluation on servers and use short timeouts. With these habits, even a complete outage of Flagsmith results in your product running with known behaviour, not breaking.
High availability costs money and adds complexity. Decide honestly how much downtime your business can accept, and design to that target. Over-building wastes budget, and under-building invites a bad night.
19The Edge Proxy and Pointing SDKs at Your Deployment
Once Flagsmith is running, your applications must find it. This chapter explains how SDKs connect and how an edge proxy can lighten the load.
Pointing SDKs at your own address
SDKs talk to the hosted Flagsmith service by default. When you run your own deployment, you give each SDK the web address of your installation through a configuration setting that every SDK supports. This single setting is how an application switches between the hosted service and your own containers. Keep the address in your application’s configuration, not scattered in code, so that changing it is a simple, safe edit.
Environment keys
Each environment in Flagsmith has keys that SDKs use to identify which environment they belong to. A client-side key is meant for browsers and mobile apps and is safe to expose, because it only reads flags. A server-side key unlocks more capabilities, such as local evaluation, and must be kept secret on servers. Using the wrong kind of key in the wrong place is a common mistake, so label them clearly.
The edge proxy
The edge proxy is a small, separate service that you run close to your applications. It keeps a copy of the flag data for the environments you choose, refreshes it from the main installation at intervals, and answers SDK questions locally. This reduces the load on the main installation and the database, keeps latency low and lets applications continue to receive answers even if the main installation is briefly unavailable. The trade-off is that its data can be slightly behind the main installation, depending on how often it refreshes, and it adds one more thing to run and monitor.
The edge proxy is a neighbourhood newsagent who receives a bundle of newspapers each morning from the central printing house. Readers in the area buy from the newsagent rather than travelling to the printing house. The news is as fresh as the last delivery, and the printing house is spared thousands of individual visits.
| Choice | Benefit | Cost |
|---|---|---|
| SDKs call the main installation directly | Always the freshest answer, fewest moving parts | All load lands on the main installation and its database |
| SDKs call an edge proxy | Lower latency, lower load, tolerance to short outages | Slightly stale data and an extra service to run |
| Server SDKs use local evaluation | Almost no network calls per decision | Rules are refreshed periodically, so changes take a moment to appear |
Choose a refresh interval that matches your tolerance for staleness. If a change must reach applications within seconds, use shorter intervals, and accept the extra load that comes with them.
20Environments, Pipelines and Infrastructure as Code
A deployment you can repeat from a description is far safer than one assembled by hand. This chapter shows how to make deployments routine.
Many environments, one design
Most teams need at least a development setup, a staging setup and a production setup. They should use the same images, the same container descriptions and the same procedures, differing only in settings such as addresses, sizes and secrets. This sameness is the great benefit of containers: what you test in staging is very close to what runs in production.
Infrastructure as code
Infrastructure as code means describing your servers, networks, databases and container settings in files that are stored in version control, instead of clicking through consoles by hand. Changes are reviewed like any other change, and the files can recreate the whole environment on demand. This protects against the dreaded “snowflake” server that nobody can rebuild because its setup lived only in someone’s memory.
Pipelines
A pipeline is an automated sequence that takes a change through steps: check, test, scan, deploy. For Flagsmith, a pipeline might validate the container description, scan the pinned images, deploy to staging, run health checks and tests, and then, after approval, deploy to production with a rolling update. Automation reduces human error and leaves a clear record of what changed and when.
Change is proposed
Someone updates a pinned version or a setting in the version-controlled description.
Checks run automatically
The pipeline validates the files and scans the images for known weaknesses.
Staging is updated
The change is applied to staging and health checks and smoke tests confirm it works.
A person approves
A responsible person reviews the results and approves the production change.
Production is updated gradually
The pipeline performs a rolling update and watches health and error rates, stopping if they worsen.
Infrastructure as code is like a recipe book kept in the kitchen instead of a dish that only one chef knows how to make. When the chef is away, anyone can follow the recipe and produce the same dish. And when someone suggests an improvement, it is written into the book, where everyone can see it.
Managing Flagsmith’s own configuration
Beyond the deployment, you may want to keep Flagsmith’s flags and settings under control through automation, using the management interface to create flags in each environment consistently. This helps keep staging and production in step and gives you a repeatable way to rebuild a lost installation.
21Performance Tuning
Most performance gains come from a few simple habits, not from heroic tuning. Here they are in order of usefulness.
First, ask fewer questions
The cheapest request is the one never made. Configure SDKs to cache answers in memory for a short time, to use local evaluation on servers, and to avoid sending identity information on every action. Poll for changes at sensible intervals instead of constantly. These client-side habits often reduce load on the deployment by a large factor.
Then, give containers the right resources
Containers need enough memory and processor time. Too little causes slowness and restarts. Too much wastes money. Set explicit limits and requests based on measurements, and revisit them when traffic changes. Run enough application copies to handle your peak with a margin, since a system running near its limit has no room for a spike.
Next, look after the database
The database is usually the first real bottleneck. Keep it on fast storage, give it enough memory so that common data stays cached, make sure indexes exist where the software expects them, and keep the database software maintained. Watch for slow queries and for the number of open connections. Use pooling when many containers connect.
Put a cache and an edge in front
Where the read load is heavy, caching and the edge proxy can absorb most of it. They trade a small amount of freshness for a large reduction in database work.
Measure before and after
Find the bottleneck
Use metrics to see whether processor, memory, database or network is the limit before changing anything.
Change one thing
Alter a single setting at a time so that you know which change produced which effect.
Test with realistic load
Use a load test that resembles real traffic, including bursts, in a staging environment.
Record the result
Write down what changed and what improved so the knowledge outlives the engineer who found it.
Tuning performance is like speeding up a busy shop. The best improvement is to stop customers asking the same question again and again, by putting the answer on a sign. Only after that does it make sense to hire more staff or enlarge the shop.
Never tune blindly in production. A wrong setting can turn a small slowdown into an outage. Rehearse changes in staging, make them one at a time and keep a way to undo each one.
22A Troubleshooting Playbook
When something goes wrong, follow the path of a request from the outside in. Most problems fall into a handful of familiar groups.
Can you reach the address at all?
Check the domain name, the certificate and the proxy. A browser warning about the certificate or a refused connection points to the front door.
Does the proxy see healthy containers?
Check that the application containers are running and passing their health checks. A proxy with no healthy targets returns errors.
What do the container logs say?
Read the most recent log lines from the application. Start-up errors usually state clearly what is missing or wrong.
Can the application reach the database?
Check the address, credentials, network membership and the database’s own health. Connection errors are the most common start-up failure.
Are migrations complete?
If the application complains about the database structure, a migration may have failed or not been run.
Is the background worker alive?
If webhooks or audit records are missing, check the task processor and its outbound network access.
Common symptoms and likely causes
| Symptom | Likely cause | First thing to try |
|---|---|---|
| Container starts then stops immediately | Missing or wrong setting, or database unreachable | Read the first error lines in the logs |
| Dashboard loads but cannot log in or shows errors | Wrong public address or allowed hosts setting | Compare the address in the browser with the settings |
| Bad request errors from the proxy path | Host name not in the allowed list | Add the public host name to the allowed list |
| Slow responses under load | Database connections or slow queries, too few containers | Check database metrics and container resource use |
| Webhooks stop arriving | Task processor stopped or blocked from outbound traffic | Check the worker’s status, logs and firewall rules |
| Data seems to vanish after a restart | Database files were not on a persistent volume | Check volume configuration and restore from backup |
| Upgrade fails midway | Migration error or incompatible versions | Stop, read logs, restore from the pre-upgrade backup if needed |
| Sudden failure after months of success | Expired certificate, full disk or rotated secret | Check certificate dates, disk space and secret versions |
| Works in staging, not in production | Different settings, networks or secrets | Compare the two configurations side by side |
Troubleshooting is like tracing a water leak in a building. You start at the street valve, check each floor in turn and narrow it down until you find the pipe that drips. Guessing at random wastes time and may flood another room.
Write down every incident, however small, with its cause and fix. After a few months, the notes become your own custom playbook, far more useful than any generic guide.
23Design Patterns and Anti-Patterns
Teams that run containers for years settle on the same few habits that work, and fall into the same few traps.
Patterns that work
Pinned, mirrored images
Exact versions copied to a private registry, so deployments are repeatable and independent of public services.
Disposable containers, durable data
Treat containers as replaceable and keep all important state in a protected, backed-up database.
Separate task processor
Background work isolated from request handling so each can be sized and watched on its own.
Single public door
Only the reverse proxy is exposed. Everything else lives on private networks.
Rolling updates with health checks
Replace containers gradually and let health checks stop a bad release before it spreads.
Edge proxy near applications
Serve flags locally to reduce latency and load, with a refresh interval chosen on purpose.
Anti-patterns to avoid
What it looks like
Production uses the latest tag and restarts pull whatever version is current.
Why it hurts
A restart can silently bring in an untested version, with database changes that are hard to undo.
Better approach
Pin exact versions, mirror them privately and change them only through a reviewed process.
What it looks like
The database runs in a container on the same single host, with its data on a plain local folder and no tested backups.
Why it hurts
A disk failure or a careless cleanup removes every flag and the full audit history with no way back.
Better approach
Use a managed database or a carefully operated one, with automated backups, off-site copies and rehearsed restores.
What it looks like
The database port is published to the internet for convenience, protected only by a password.
Why it hurts
Automated scanners find open database ports quickly, and weak or leaked passwords lead to full compromise.
Better approach
Keep the database on a private network and reach it only from the application and worker containers.
What it looks like
Secrets are written into the image, the container description or a shared document.
Why it hurts
Anyone with access to the image or the file can read them, and they are difficult to rotate.
Better approach
Use a secrets manager or orchestrator secrets and inject values only when containers start.
What it looks like
Nobody monitors the task processor, and upgrades are skipped until they become frightening.
Why it hurts
Webhooks and audit processing fail silently, and eventually a large, risky upgrade becomes unavoidable.
Better approach
Monitor every component, upgrade in small regular steps and test each one in staging first.
24Best Practices and Common Mistakes
A compact checklist of habits that pay off, and mistakes that cause pain.
Best practices
- Pin exact image versions and mirror them in a private registry.
- Keep all state in a protected, backed-up database.
- Prefer a managed database for production.
- Expose only the reverse proxy, over HTTPS.
- Store secrets in a manager and rotate them regularly.
- Run a dedicated task processor and monitor it.
- Add health checks to every container.
- Take and test backups, and write down recovery targets.
- Upgrade in small steps, with staging first and a backup before.
- Describe the whole setup as code in version control.
Common mistakes
- Using the latest tag in production.
- Publishing the database port to the internet.
- Forgetting to include the public host name in the allowed list.
- Putting database files on temporary container storage.
- Running multiple new containers that all try to migrate at once.
- Never restoring a backup to see if it works.
- Ignoring certificate expiry dates.
- Giving containers more privileges than they need.
- Leaving the task processor unmonitored.
- Letting a single engineer be the only person who understands the setup.
Protecting against the single expert problem
A self-managed deployment often begins as one person’s project. The risk is obvious: when that person leaves or is unavailable, the knowledge leaves with them. Share the on-call duty, keep the setup written down in version control, rehearse recovery with different team members and keep a short runbook where everyone can find it.
Protecting against drift
Over time, hand-made changes make environments differ from their descriptions, which is called drift. Avoid it by making all changes through the version-controlled files and the pipeline, and by periodically comparing the running system with the description. A deployment that can be rebuilt from its description is a deployment you can trust.
Once a quarter, run a short drill: restore a backup into a clean environment, roll out an upgrade in staging and review the alerts. Boring rehearsals make real incidents calmer.
25A Worked Example: From Laptop to Production
Let us follow an imaginary team as it grows its Flagsmith deployment in three stages, so you can see the ideas in a real-feeling sequence.
The team
Imagine a company called Harbourline that makes scheduling software for clinics. It has twenty-five engineers, a website, a mobile app and an internal operations group of three people. The product team wants gradual rollouts and quick kill switches. Because customer data is sensitive and a few clinics ask where their data lives, the company decides to self-host Flagsmith using containers.
Stage one: the laptop
A developer first runs Flagsmith on a laptop using a single container description that starts the application and a database container. Within an hour, the team sees the dashboard, creates a flag and connects a test application. The lesson at this stage is understanding, not durability. Nobody worries about backups, because the data is disposable. The developer writes down every setting used and which image version was pulled.
Stage two: a shared staging server
Next, the team sets up a staging environment on a small cloud machine. They keep the container description in version control, pin exact image versions, put a reverse proxy with an HTTPS certificate in front, and move secrets into the cloud’s secret storage. The database moves to a managed service with automatic backups, and the staging environment gets its own network. The team runs one backup restore as a drill and discovers a missing permission, which they fix. They also add health checks and a basic dashboard of request rate, errors and database connections.
Stage three: production
For production, the operations group builds on the staging design. Three application containers run across two availability zones behind a load balancer. A dedicated task processor runs in each zone. The managed database has a standby copy in a second zone and backups copied to a separate account. A mirrored, scanned copy of each image lives in the company’s private registry. An edge proxy runs in the same network as the application servers, so server code receives flag answers within a millisecond or two. A pipeline deploys changes: staging first, then production through a rolling update after approval.
flowchart LR
A["Stage 1: Laptop with one description and a test database"] --> B["Stage 2: Staging server with proxy, HTTPS, managed database and secrets"]
B --> C["Stage 3: Production in two zones with load balancer and standby database"]
C --> D["Stage 4: Edge proxy, pipeline, drills and quarterly reviews"]
B -.-> E["Lesson: backups need a restore drill"]
C -.-> F["Lesson: monitor the task processor"]
D -.-> G["Lesson: upgrade in small regular steps"]
Reading the picture
The solid line shows the growth of the deployment. The dotted lines show the lessons learned at each stage. Notice that complexity was added only when the need appeared. The laptop needed understanding, staging needed repeatability and security, and production needed redundancy and discipline. At no point did the team build for a scale it did not have.
Harbourline’s path is like a food business growing from a stall to a restaurant to a chain. At the stall, you cook for yourself and learn the recipe. In the restaurant, you add hygiene rules, a proper kitchen and a trained team. In the chain, you add standard procedures, inspections and backup suppliers. Each stage builds on the last without throwing away what worked.
What happened on a bad day
A zone has trouble
One availability zone loses networking. The load balancer’s health checks notice, and traffic moves to containers in the other zone.
The database fails over
The managed database promotes its standby copy. The application reconnects after a short interruption.
Apps barely notice
SDKs use cached answers and local evaluation, so users see no change. A few alert messages reach the on-call engineer.
Webhooks catch up
The task processor resumes after the failover and clears its small backlog. The on-call engineer checks the backlog age to confirm.
Review the next day
The team writes a short note on what happened, how long recovery took and which alert was most useful.
Grow in stages and stop when your needs are met. Every extra layer of redundancy is one more thing to understand, secure and pay for.
26A Production Readiness Checklist
Before you declare a deployment ready for real traffic, walk through this checklist honestly. Each unchecked line is a small risk you have agreed to carry.
Images and configuration
- Every image is from the official publisher, pinned to an exact version and mirrored privately.
- Images have been scanned and the results reviewed.
- All settings are in version-controlled files, and all secrets are in a secrets manager.
- The public address, allowed hosts and dashboard-to-API settings all agree.
Data
- The database is managed or carefully operated, on a private network, with encryption enabled.
- Automated backups run, are copied off-site and are encrypted.
- A restore has been rehearsed recently, and the time taken is recorded.
- Recovery point and recovery time targets are written down and met.
Network and security
- Only the reverse proxy is public, with a valid certificate and automatic renewal.
- Containers run as normal users with minimal privileges, and none mount the engine’s control socket.
- Dashboard users have individual accounts, least-privilege roles and multi-factor authentication where available.
- Automation keys are stored safely and have a rotation plan.
Operations
- Health checks exist for every container.
- Logs go to a central place with sensible retention.
- Alerts cover errors, latency, restarts, disk space, database connections, task backlog, certificates and backups.
- A runbook exists, and at least two people can follow it.
- An upgrade procedure has been tested in staging.
Application side
- Every flag read has a safe default value in code.
- SDKs use caching and, on servers, local evaluation.
- The service address is a single configuration setting.
- A test has shown how the product behaves when Flagsmith is unreachable.
| Area | Ready if you can say | Warning sign |
|---|---|---|
| Images | We know exactly which versions run and where they came from | We use latest or an unknown copy |
| Data | We restored a backup last quarter and it worked | Backups exist but nobody has tried them |
| Network | Only the proxy is reachable from outside, and we tested it | We assume the firewall protects us |
| Secrets | No secret appears in images, files or chat | Shared passwords and old keys |
| Monitoring | We would know before users complain | We hear about problems from customers |
| Upgrades | We upgrade on a schedule with a tested rollback | We are many versions behind |
| People | Two or more people can run and fix it | Only one person understands it |
The readiness checklist is the pilot’s walk-around before take-off. The aircraft may look perfect from the cockpit, but the pilot still checks the tyres, the fuel and the control surfaces. Those few minutes of dull inspection are what make the flight uneventful.
If you cannot tick most of these lines, that is not a failure. It is a map of the work still to do. Launch in a limited way, such as for internal tools first, while you close the gaps.
27Lessons from the Wider Container World
Containers have been used in production for years by many well-known companies. Their experience offers lessons that apply directly to a Flagsmith deployment.
Streaming platforms: expect failure and practise it
The streaming company Netflix became known for deliberately breaking parts of its own systems in production to prove that the rest keeps working. The lesson for your Flagsmith deployment: do not just assume that a failed container, a failed zone or an unreachable flag service will be survivable. Switch something off on purpose, in a safe way, and watch what your applications do.
Search and cloud giants: orchestration as a foundation
Google ran containers at huge scale for many years and the lessons from its internal systems led to the creation of Kubernetes, now used across the industry. The lesson: orchestrators exist because running many containers by hand does not scale, but small teams should adopt them only when they have the need and the skills.
Ride-hailing and delivery companies: disposable parts, durable data
Companies such as Uber run vast numbers of short-lived containers while keeping their critical data in carefully engineered storage systems. The lesson: make containers disposable and put your effort into protecting the data layer. This is exactly the shape of a sound Flagsmith deployment.
Online retailers: scale for the peak, not the average
Large retailers such as Amazon prepare their systems for the busiest days of the year, not the average day. The lesson: test your deployment with a burst larger than anything you have seen, including a burst of flag changes and webhooks, because peaks arrive when failures hurt most.
Software platforms: supply chain care
Software supply chain incidents, in which a trusted package or image was tampered with, have taught the industry to pin versions, verify sources, scan images and keep private mirrors. The lesson: the image you pull is code that runs inside your network, so treat it with the same care as code you wrote.
These examples illustrate general practices that are widely discussed in the industry. Details of each company’s systems change over time, so treat them as illustrations, not as specifications.
28Glossary of Terms
Every important word used in this guide, in plain language, for quick lookup.
| Term | Plain meaning |
|---|---|
| Container | A running, isolated instance of an application packaged with everything it needs. |
| Image | A read-only template from which containers are created. |
| Registry | An online library where images are stored and shared. |
| Tag | A label, often a version number, that points to a particular image build. |
| Digest | A long fingerprint that identifies one exact image permanently. |
| Volume | Storage kept outside a container so data survives replacement. |
| Bind mount | A folder on the host machine made visible inside a container. |
| Environment variable | A named setting passed to a container when it starts. |
| Compose | A tool that describes and runs a group of containers from one file. |
| Orchestrator | A system that runs containers across many machines and keeps them healthy. |
| Kubernetes | The most widely used container orchestrator. |
| Reverse proxy | A front door that accepts outside connections, handles encryption and forwards requests. |
| TLS and HTTPS | The encryption that protects web traffic, proven by a certificate. |
| Load balancer | A traffic director that spreads requests across several copies of a service. |
| Stateless | Describing a service that remembers nothing between requests, so any copy can answer. |
| Migration | A scripted change that brings the database structure up to date. |
| Rolling update | Replacing containers one at a time so the service stays available. |
| Health check | A small test that tells the platform whether a container is working. |
| Task processor | The background worker that runs jobs such as webhooks and audit processing. |
| Edge proxy | A small service near your applications that serves flags from a local copy of the data. |
| Local evaluation | Letting a server SDK hold the rules and decide flags without a network call. |
| Availability zone | A separate data centre area within a region, with independent power and networking. |
| Failover | Automatically switching to a standby copy when the primary fails. |
| Recovery point objective | How much recent data you can afford to lose after a failure. |
| Recovery time objective | How long you can afford to be down while recovering. |
| Infrastructure as code | Describing servers and settings in version-controlled files that can recreate them. |
| Drift | The gradual difference between a running system and its written description. |
29Frequently Asked Questions
Short answers to the questions people ask most often when deploying Flagsmith in containers.
30Summary and Key Takeaways
Everything in this guide comes down to a handful of ideas you can carry into your next deployment.
Docker turns Flagsmith from a pile of installation steps into a repeatable package. The application, dashboard, task processor and edge proxy are disposable containers. The database is the precious part. A sound deployment puts a reverse proxy at the only public door, keeps everything else on private networks, pins and mirrors its images, stores secrets safely, monitors every component and practises its backups and upgrades. It grows in stages, only as far as the need requires, and it leaves your applications able to carry on even when the flag service cannot answer.
Key Takeaways
- Disposable containers, durable data. Treat the application containers as replaceable and put your protection effort into the database, its backups and its recovery.
- Pin and mirror images. Use exact version tags from the official publisher, scan them and keep private copies so that deployments are repeatable and independent of public services.
- One public door. Expose only the reverse proxy over HTTPS, keep the database and workers on private networks, and make the public address agree everywhere it appears.
- Configure with care. Keep secrets in a secrets manager, never in images or shared files, and take setting names only from the documentation for your exact version.
- Separate and watch the background work. Run a dedicated task processor for production, and monitor its backlog, because its failures are silent.
- Upgrade calmly and rehearse recovery. Back up first, test in staging, migrate once, replace gradually, and prove regularly that a restore really works.
- Design the applications for the bad day. Use safe default values, SDK caching, local evaluation and an optional edge proxy so your product keeps working even if the flag service does not.