On this page
Why you almost never want to run your own database
Installing a database is easy. apt install postgresql, and you're running. Keeping a database alive in production is a different job entirely: nightly backups you've actually tested restoring, security patches the week they drop, replication so one disk failure isn't game over, monitoring for the slow creep toward a full disk, and a plan for when the server dies at 3am. That work never ends, and it's nobody's idea of building a product.
A managed database, AWS RDS, Aurora, DynamoDB, and their equivalents, hands all of that to the cloud provider. They run the server, patch it, back it up, replicate it, and fail it over when hardware dies. You get a connection string and a bill. The interesting decision shifts from *how do I keep this alive* to *which kind of database fits my data*, and that's what this article is really about.
Who this is for
Beginners choosing a database for the first time, or anyone who's only ever used one type and isn't sure when to reach for the other. No deep database theory required. Examples lean on AWS names, but the trade-offs are universal.
What "managed" actually buys you
A managed database is one where you own the data and the schema, and the cloud provider owns the server, the patching, the backups, the replication, and the failover.
The split of responsibility is the whole value. Think of it like the difference between owning a car and using a chauffeur service, you still decide where to go and what to carry, but someone else handles the engine, the oil changes, and the breakdowns.
Yes, you pay a premium over a raw server. For almost everyone, the engineering time saved, and the outages avoided, is worth far more than the markup. Self-host only when you have a specific, costed reason and the in-house expertise to do the operational work properly.
The big fork: relational vs NoSQL
Once you've decided on managed, the real choice is the data model. Relational (SQL, Postgres, MySQL, Aurora) stores data in tables with rows and columns and a fixed schema, and lets you join tables together with rich queries. NoSQL (DynamoDB, MongoDB, and friends) is a family of models, most commonly key-value and document, built for massive scale and flexible structure, usually at the cost of joins and some guarantees.
| Relational (SQL) | NoSQL | |
|---|---|---|
| Data shape | Tables, fixed schema | Documents / key-value, flexible |
| Relationships | Joins across tables, built-in | Denormalise; joins are your job in code |
| Query power | Rich, ad-hoc queries via SQL | Fast on known access patterns; limited ad-hoc |
| Consistency | Strong, transactional (ACID) | Often eventual; tunable on some stores |
| Scaling | Scales up; read replicas for reads | Scales out horizontally, near-limitless |
| Best for | Most apps: orders, users, anything related | Huge scale, simple lookups, flexible/changing shape |
Pro tip
The honest default for most projects: start relational. SQL is flexible, well-understood, and handles the vast majority of apps comfortably. Reach for NoSQL when you have a specific, identified need, extreme scale, a known simple access pattern, or genuinely schema-less data, not because it sounds modern.
When each one actually fits
Reach for relational when…
- Your data has relationships, users have orders, orders have items, items belong to products. Joins make this natural.
- You need transactions, money moving, inventory decrementing, where "all of it or none of it" must be guaranteed.
- You'll ask questions you can't predict yet. SQL lets you query any way later without redesigning storage.
- You're not at a scale that a big single instance plus read replicas can't handle, which is most apps, for a long time.
Reach for NoSQL when…
- You have a simple, known access pattern at huge scale, "give me this user's session by their ID" billions of times.
- Your data is naturally document-shaped or its structure varies per record (flexible, evolving fields).
- You need to scale writes horizontally beyond what a single relational primary can take.
- You can live with eventual consistency for that workload (e.g. a view counter, an activity feed).
"NoSQL because it scales" is the classic over-engineering trap
Teams reach for NoSQL early "so it'll scale," then spend months reimplementing joins and transactions in application code, the exact things SQL gives you for free, while never hitting the scale that justified it. Choose for the data shape and access pattern you actually have, not the one you imagine.
Staying alive: Multi-AZ vs read replicas
Two features get confused constantly because both involve "another copy" of the database. They solve completely different problems. Multi-AZ is for survival; read replicas are for speed.
| Multi-AZ | Read replicas | |
|---|---|---|
| Solves | Survival, what if the database dies? | Speed, too many reads for one server |
| The copy is | A standby in another availability zone | One or more readable copies |
| Can you read from it | No, standby is idle until failover | Yes, that's the whole point |
| On primary failure | Auto-fails over to the standby | Replicas keep serving reads; you promote one |
| Reach for it when | Always, for anything that matters | Reads outgrow a single instance |
Multi-AZ keeps a synchronised standby copy in a different availability zone. If the primary's hardware dies, the cloud promotes the standby automatically, usually within a minute or two, and your connection string keeps pointing at "the database." You don't read from the standby; it exists purely to take over.
Read replicas are extra copies you *can* read from. If your app reads far more than it writes (most do), you send reads to replicas and writes to the primary, spreading the load. Replicas are usually eventually consistent, a write may take a moment to appear on them, so don't read something back from a replica immediately after writing it to the primary.
Pro tip
For anything you'd be upset to lose, turn on Multi-AZ from day one, it's the database equivalent of running across two AZs for your app. Add read replicas later, only when read load actually demands it. Survival first, speed when you need it.
Common mistakes that cost hours (or data)
- Self-hosting a database to save money, then losing data. The savings evaporate the first time an untested backup fails to restore. Use managed unless you have a real reason and the expertise.
- Picking NoSQL "to scale" before you need to. You'll rebuild joins and transactions by hand and rarely hit the scale that justified it. Default to relational.
- Confusing Multi-AZ with read replicas. Multi-AZ is for survival (you can't read from it); replicas are for read scaling. Turning on replicas does not give you automatic failover.
- Reading from a replica right after writing. Replicas are eventually consistent; the write may not be there yet. Read-after-write goes to the primary.
- No tested restore. "We have backups" means nothing until you've actually restored one. Practise the restore before you need it for real.
- Putting the database in a public subnet. A managed database should have no public IP, reachable only from your app tier inside the private network.
Where to go next
The whole article in 6 lines
- **Managed databases** hand server, patching, backups, replication, and failover to the cloud, use them by default.
- The real choice is the **data model**: relational (related data, transactions, ad-hoc queries) vs NoSQL (simple access at huge scale, flexible shape).
- **Default to relational**; reach for NoSQL only for a specific, identified need.
- **Multi-AZ = survival** (a standby that auto-fails-over; you can't read it). **Read replicas = speed** (readable copies for read-heavy apps).
- Don't read from a replica right after writing, replicas are eventually consistent.
- A backup you haven't restored isn't a backup. Keep the database in a private subnet.
Choosing and running data stores well is a core cloud skill. Keep going:
- Understand the storage layer underneath databases: Cloud Storage: Object, Block & File.
- Make "staying alive" rigorous with real targets: High Availability & Disaster Recovery (RTO/RPO).
- See where databases fit the full role: the Cloud Engineer path.
Spin up a managed Postgres with Multi-AZ on, point a small app at it, then practise restoring a backup. Once you've watched the cloud handle a failover for you, you'll understand exactly why almost nobody runs their own database anymore.
Want to go deeper?
This article covers concepts taught hands-on in the Cloud Engineer and DevOps career paths, with real terminal labs, production scenarios, and structured lessons.