In the previous post, I introduced a real migration scenario where a client, in the process of modernising their application, made an interesting architectural choice - to run their MySQL database inside a container alongside the rest of their services.
At first glance, the approach made sense. The entire application was being redesigned around containers. Keeping everything consistent felt clean and intuitive. But as we explored in the first post, databases don’t behave like the rest of your application. They are stateful, performance-sensitive, and operationally demanding in ways that don’t always align with container-first design patterns.
The real challenge wasn’t whether the database could run in a container.
It was whether it should, especially for a production database, and when there are other options available that may be better suited to the nature of database workloads.
And that is where the conversation shifted.
Instead of focusing on a single approach, we stepped back and evaluated three distinct options for hosting the database on AWS:
- Running the database as a container on AWS Fargate
- Hosting the database on a virtual machine using Amazon EC2
- Using a managed service like Amazon RDS
Now, there are several factors to consider here – but for this piece, we will focus on three main ones:
- Storage management
- Backup and recovery
- Operational overhead
Option 1: Containerised Database on ECS Fargate
In this model, the MySQL database runs as a container on Amazon ECS, using AWS Fargate for compute. Persistent storage is attached externally – via EFS or EBS.
First, let’s look at why this pattern is appealing:
- It provides consistency across environments. The same container can run in development, testing, and production
- You get a unified deployment pipeline. Your database, rather than being an independent component, becomes just another service in your CI/CD workflow
- Reduced infrastructure management. Fargate is serverless. So there is the added advantage of not having any servers to provision or manage directly.
None of these are trivial benefits - they’re part of what makes containers powerful.
Now, let’s take a look at the other side:
a) Persistent Storage Options for ECS Fargate
Containers, as we’ve already seen, are designed to be ephemeral. They can be stopped, replaced, or rescheduled at any time. Databases, on the other hand, expect stability. To bridge that gap, external storage must be introduced into the architecture.
ECS Fargate supports both EFS (for file storage) and EBS (for block storage). Let’s compare these two options:
EBS: Strong Performance, but Tightly Coupled to Task Lifecycle
When attached to a Fargate task, EBS volumes provide block-level storage with predictable IOPS, which is ideal for database workloads that demand low-latency reads and writes. The volume persists beyond the life of a task, so your data survives container restarts.
The challenge, however, is that Fargate only allows for a single volume per task. You got one task – well and good. But the constraint shows up when the application scales, creating multiple tasks each requiring its own volume. Over time, you’ve got dozens of volumes to track, monitor, and manage, which can be an admin nightmare.
Additionally, resizing an EBS volume that is attached to a Fargate task often requires stopping the task, detaching the volume, resizing it, and then reattaching it to a new task. This type of manual orchestration introduces downtime and complexity into the environment.
EFS: Operational Simplicity with Performance Trade-offs
The key strength of EFS over EBS, on the other hand, is that the file system can be mounted simultaneously across multiple Fargate tasks.
Because it's shared, there is no need to provision a separate volume per task. This eliminates the volume sprawl problem.
More importantly, EFS is natively integrated with Fargate, meaning mounting it is a simple configuration, and it scales automatically as storage grows.
So what is the drawback? EFS is file storage. This means that all I/O operations occur over the network. For a database, this means that it will experience higher latency, throughput, and IOPS will be less predictable – especially under concurrent access, and the performance can degrade under sustained transactional workloads. Overall, EFS introduces file locking and consistency considerations that are not ideal for relational databases.
So, at a high level, EBS optimises for performance predictability, while EFS optimises for operational simplicity and scalability.
b) Backup and Recovery Complexity
This is where Fargate becomes especially difficult to defend for a production database.
Docker containers do not easily persist the user space. You cannot snapshot a container to get a physical database backup the same way you can with a VM or a logical volume. This creates a significant challenge; obtaining a physical DB backup (which is strongly preferred for faster restore times) is not straightforward.
The alternative is to fall back on logical backups. Logical backups can be obtained either by running scheduled tasks or utilizing sidecar containers to execute a mysqldump to an external storage service, e.g., S3. While this works, it also has some drawbacks:
- Significantly slower backup and restore times. Logical backups work by exporting data as SQL statements. When taking a backup, data must be read row-by-row. During restore, the database must first recreate the schema, then similarly re-insert data row by row. For a small database, this may be fine. But as your database grows, restores can stretch from minutes to hours – even days.
- Logical backups are resource-intensive. There’s generally increased load on the database due to actions such as full table scans and serialization. For an environment such as Fargate, where resources are already constrained, this could result in slower queries and degraded application performance during backup windows.
- Logical backups don’t provide true Point-in-time-Recovery (PITR). Since logical backups are taken at a specific point, any data between backup windows is usually lost. To achieve true Point-in-time-Recovery, additional configuration would be required, e.g., setting up binary log management.
So, what about EBS Snapshots? Could we not obtain a physical backup from that? Yes, we could. EBS Snapshots provide faster backups, faster restores, and better alignment with low RTO – all of which solve the issue of slow recovery.
However, the disadvantage of EBS snapshots is that, alone, these snapshots are not application-consistent for live databases without carefully quiescing writes first. This means that you can restore a snapshot and end up with corrupted data or an inconsistent state.
Additionally, snapshots still do not provide PITR, which is critical for a production database.
So, while snapshots give you speed, logs provide precision and are just as critical to build a reliable recovery strategy on ECS Fargate. Simply put, you don’t get a complete backup strategy out of the box; you have to build it yourself.
Conclusion: Just Because You Can…
Where Constraints Start to Matter
So, where does this leave us?
Yes, you can run a database on Fargate.
On storage, you have legitimate options. EBS gives you predictable block performance with the constraint of one volume per task, while EFS gives you shared, scalable storage that eliminates volume sprawl but with different performance characteristics.
Even on the backup side, it’s entirely feasible to design a working strategy. With the right combination of logical backups, snapshots, and operational processes, you can achieve reliable backup and recovery.
So, the real question becomes not ‘Can you run a database on Fargate?’ but rather ‘What type of database can you run on Fargate?’
For development and testing environments? For low-throughput internal tools? For databases small enough that a slow logical restore doesn't ruin anyone's week? Fargate can be a perfectly reasonable choice.
But for production-grade, performance-sensitive systems, these constraints compound quickly. At that point, the trade-offs we’ve discussed, storage complexity, backup orchestration, and performance variability, stop being theoretical concerns and start becoming real operational challenges.
Why Context Matters
Back to our client.
The thing about architecture is that you often don’t land at a single technical solution. In fact, the majority of the time, you’ll have at least 3 workable options where you only need one. So, how do you determine which is which?
Remember the background I shared in Part 1? The context a client shares often comes in handy in determining which of your options is the most viable. For my client, I had 2 additional factors from their background that I needed to consider.
1. The Learning Curve
This client was only just beginning their containerisation journey – having previously solely run on a traditional monolithic setup. Let’s break that down further:
- They are new to microservices and containerised environments. The team is on a learning curve, building new skills, figuring out deployment patterns, and learning how to debug distributed systems.
- They are also migrating to a cloud platform they are new to. AWS, with its dozens of services and unfamiliar operating models, represents another significant learning curve all on its own. Two steep learning curves, happening simultaneously. Adding a complex, stateful workload in a containerised environment on top of that would mean introducing another layer of operational complexity - right at the point where the team is still building foundational knowledge.
2. Growth and Future Scale
The client had made one thing very clear: they were anticipating significant user growth in their new market. A key objective of the migration was to get ahead of that growth. This meant resiliency and scalability weren't nice-to-haves. They were core requirements.
We had to design for the future, not just for the day after launch, but for six months and a year down the road when their user base had doubled or tripled. Would a manually managed backup pipeline still hold up? Would the one-volume-per-task constraint become a scaling bottleneck? Would the team, still learning AWS and containers, be able to respond quickly when something broke?
Taken together, these factors made one thing clear - while running the database in a container aligned with the client’s initial vision, it introduced risks that didn’t align with their long-term goals. And that is why we had to step back and consider alternatives.
In the next blog piece, we will look at two alternative approaches: EC2 and RDS. Because in the end, choosing where your database lives isn’t just a technical decision, it’s an operational one. And getting it right early can save you from a lot of pain later.
Top comments (0)