Section 3 · Core Services
Databases: Amazon RDS vs Amazon DynamoDB
15 min3 min readChoose wisely
Lesson at a glance
Choose between Amazon RDS and Amazon DynamoDB from a workload’s access patterns, and set each one up with backups, encryption and private access from the start.
- 1Amazon RDS: your SQL database, run for you
- 2Amazon DynamoDB: design the keys, get speed at any scale
- 3Choosing
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
Lantern’s old server had one PostgreSQL database for everything: events, venues, organisers and every RSVP. During the festival spike, RSVP writes queued up behind a slow report query and the whole site stalled. On AWS you can give each kind of data the database that suits it. The two you will meet first are Amazon RDS and Amazon DynamoDB, and they differ in almost every way that matters.
Amazon RDS: your SQL database, run for you
Amazon Relational Database Service runs a relational engine on infrastructure AWS manages. Engines include PostgreSQL, MySQL, MariaDB, Oracle, SQL Server and Db2, plus Amazon Aurora, AWS’s own MySQL- and PostgreSQL-compatible engine.
AWS takes on the chores Lantern used to do at 2 a.m.: provisioning, OS and engine patching in a maintenance window you choose, automated backups with point-in-time recovery, and Multi-AZ deployments with a synchronous standby in another Availability Zone that takes over automatically. You still own the schema, indexes, queries, database users, the instance size, and who can connect.
Here is how Lantern creates its events database, with the safe choices spelled out:
aws rds create-db-instance \
--db-instance-identifier lantern-events \
--engine postgres --db-instance-class db.t4g.micro \
--allocated-storage 20 --storage-encrypted \
--master-username lantern_admin --manage-master-user-password \
--backup-retention-period 7 --multi-az \
--no-publicly-accessible--manage-master-user-password stores the admin password in AWS Secrets Manager instead of your shell history. --no-publicly-accessible keeps the database off the internet; next lesson puts it in a private subnet. And because Lantern’s existing app speaks SQL, migrating is a pg_dump and a restore, with the queries unchanged:
SELECT v.name, date_trunc('month', e.starts_at) AS month, count(*) AS events
FROM events e
JOIN venues v ON v.id = e.venue_id
GROUP BY v.name, month
ORDER BY month DESC, events DESC;How RDS bills: per instance-hour (with Savings Plans or reserved instances for steady use), plus storage per GB-month, backups beyond a free allowance, and data transfer. A Multi-AZ deployment roughly doubles the instance cost because there are two instances. Crucially, the instance bills all month whether busy or idle. Aurora Serverless v2 can scale capacity with load and pause when idle, which suits spiky or development databases.
Amazon DynamoDB: design the keys, get speed at any scale
DynamoDB is a serverless key-value and document database. There is no instance to size: you create a table, choose a primary key, and read and write items (JSON-like documents) with consistent single-digit-millisecond latency, at ten requests a day or tens of thousands a second.
The catch is that you design the keys around the questions you will ask. For RSVPs, Lantern’s questions are “who is coming to event X?” and “has this person already RSVPed to X?”. That gives a partition key of eventId and a sort key of email:
aws dynamodb create-table --table-name lantern-rsvps \
--attribute-definitions AttributeName=eventId,AttributeType=S \
AttributeName=email,AttributeType=S \
--key-schema AttributeName=eventId,KeyType=HASH \
AttributeName=email,KeyType=RANGE \
--billing-mode PAY_PER_REQUESTCounting the RSVPs for one event is then a cheap Query:
aws dynamodb query --table-name lantern-rsvps \
--key-condition-expression "eventId = :e" \
--expression-attribute-values '{":e": {"S": "evt-2026-street-food"}}' \
--select COUNTHow DynamoDB bills: in on-demand mode (PAY_PER_REQUEST), per read and write request plus storage per GB-month, and nothing for idle time. Provisioned mode, with auto scaling, can be cheaper for steady, predictable traffic. Start on-demand; switch only when the bill shows steady load. Point-in-time recovery is a setting you turn on per table, and you should.
Choosing
| Question | RDS | DynamoDB |
|---|---|---|
| Are the questions varied or ad hoc? | Yes: SQL handles new ones | No: keys answer known ones |
| Need joins and multi-table constraints? | Yes | Rarely; you denormalise |
| Traffic spiky, with idle time? | Pays for idle hours | Pays per request |
| Existing SQL code to keep? | Keep it | Rewrite data access |
| Ops you still do | Sizing, connections, upgrades | Key design |
Lantern ends up with both: events, venues and organisers in RDS for PostgreSQL, where reports and the existing admin pages work unchanged; RSVPs in DynamoDB, where a viral event’s write spike costs a few cents of requests instead of stalling the shared database.
The database is private, but private from what? Next lesson builds the network Lantern’s pieces live in.
Key takeaways
- Amazon RDS runs a relational engine such as PostgreSQL for you, handling patching, backups and Multi-AZ failover, while you own the schema, queries and connections.
- Amazon DynamoDB is a serverless key-value and document database where you design the keys around the questions you will ask.
- RDS bills mostly per instance-hour, whether busy or idle; DynamoDB on-demand bills per request and per gigabyte stored.
- Use a DynamoDB Query on keys for hot paths, because a Scan reads and bills the whole table.
- Many real systems use both, relational data in RDS and high-volume simple lookups in DynamoDB.