AWS RDS for production: Terraform, Multi-AZ, monitoring

A production database loses resilience unnoticed: failover is configured only formally, and monitoring stays silent. We set up AWS RDS turnkey — design the configuration, deploy it, and hand over documentation to the team. Incident resolution time is reduced severalfold.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Configuring AWS RDS: where the production database loses resilience

A managed database in RDS is not the same as a fault-tolerant one: by default the instance sits in a single Availability Zone, and snapshots are taken once a day.

If the zone fails, recovery runs from the last snapshot — that means hours of downtime and the loss of some confirmed transactions. For a production database, such a setup means that any failure on the provider side turns into an incident requiring manual investigation.

Storage is the second hidden point of failure. Autoscaling does not kick in instantly and still hits the configured limit: when space runs out, the database goes read-only, and writes stop long before the alert fires.

The third is connections. Under peak load the application opens hundreds of connections, the instance hits its limit and starts rejecting new ones, even though the CPU is nowhere near its ceiling. This is solved with a connection pool and tuned parameters, not by increasing the instance size.

Separately, there is configuration drift: parameters are edited by hand through the console, they never make it into Terraform, and the test environment stops matching production.

When a rollback or an environment copy is needed, there is nothing to reproduce the database behavior from. And without metrics on free space, active connections, and replica lag, the cause of a failure is only looked for after the fact — during the postmortem, not before it.

We break down these points of failure and how each one gets closed.

What changes after bringing order to the configuration

If a managed database is tied to a single Availability Zone, its failure turns into service downtime for the entire duration of manual recovery from a snapshot.

After moving to a mode with a standby node in another zone, a zone failure stops being an event for users: failover happens automatically, the application reconnects to the same address, and unavailability is measured in tens of seconds rather than hours.

Recovery time becomes predictable, because the parameters are set in configuration rather than in the on-call engineer's head.

The snapshot schedule, retention depth, maintenance window, and point of recovery are fixed and versioned along with the rest of the infrastructure — an engineer can see how far back they can roll before work even begins.

Database monitoring is built around symptoms rather than the fact of an outage: alerts on connection count growth, replica lag, disk filling up, a spike in write latency, and connection errors arrive before users notice any slowdown.

Every signal has a threshold and an owner, so degradation is handled as routine work rather than in emergency mode.

Overall, the class of failures changes: a zone failure does not stop the service, downtime during planned maintenance shrinks to the moment of failover, and incidents become visible before complaints do.

Configured this way, AWS RDS delivers not a one-off result but a reproducible one: scenarios — node failure, disk overflow, a failed migration — are described in advance, and each has a proven action.

RDS fault-tolerance modes and their real limitations

The redundancy mode is chosen once — at the Terraform module level — and rarely changes without recreating the instance.

AWS RDS offers several placement schemes, and they are not interchangeable: one covers an Availability Zone failure, another covers read load, a third covers the loss of an entire region.

Option When it fits Limitations
Single Availability Zone Internal services and test environments where several hours of downtime are acceptable No failover: a zone failure means recovery from a copy with a lag equal to the snapshot interval
Multi-AZ with a standby copy A production environment that only needs to survive a zone failure The standby takes no traffic and sits idle; analytics still loads the primary database
Multi-AZ cluster with readable copies You need both fast failover and read scale Not available for all editions; the application must reconnect, old connections are dropped
Read replica Offload reports from the primary database, prepare an environment for growth Asynchronous replication: lag, inconsistent reads, manual promotion
Cross-region replica A requirement to survive the loss of an entire region Double maintenance, long failover, loss of the latest transactions

The trap of a managed database is that fault tolerance looks like a toggle. Any mode more complex than a single instance requires the application to reconnect to a new address and schema migrations not to block failover.

That is why we describe the connection endpoint separately from the instance and test behavior in a training failure before going to production.

Deployment and configuration validation stages

Spinning up an instance in the console takes ten minutes, but the parameters, replicas, and backup windows stay in the web interface: they are not reviewed, they drift between environments, and after a failure the configuration has to be reproduced from memory. That is why we run deployment as a fixed sequence.

  1. Configuration audit — we capture the instance class, Multi-AZ mode, backup window, parameter group, access from public subnets, and snapshot retention period.
  2. Schema design — private subnets in two Availability Zones, security group, storage encryption, read replica, maintenance window outside peak hours.
  3. Infrastructure as code — the instance, subnet group, parameter group, alert rules, and backup policy are described in a Terraform module; state lives in a remote backend with locking, and changes go through review only.
  4. Load testing — we reproduce the real query profile and capture metrics in CloudWatch: latency, connection count, write queue. We separately test failover when the primary node fails.
  5. Production cutover — traffic is moved via a replica and a snapshot, the write window is minimal, and the rollback procedure to the previous setup is described in advance.
  6. Handover — dashboards, alert thresholds, a procedure for planned parameter changes, and instructions for restoring from a snapshot.

A parameter change goes through review in code rather than in the console, and any environment is spun up from the description exactly one-to-one. That is what a verifiable configuration is, rather than a set of manual settings that a single engineer remembers.

Artifacts and documentation the team keeps

Infrastructure artifacts are not an acceptance report but working tools. We assemble them so that your engineer can spin up an identical environment, make a parameter change, or restore a cluster after a failure without back-and-forth with us.

  • Environment diagram — how many there are and how they differ: where Multi-AZ is enabled, which instance classes, snapshot retention periods, and why.
  • Configuration description — the structure of the Terraform module, the purpose of variables, where state is stored, and how to connect a new service to the database.
  • Network and access diagram — subnets, security groups, IAM roles, and through which node developers connect to production.
  • Access policies — separation of roles: who changes cluster parameters, who only views metrics, and how administrators' actions are logged.
  • Backup procedure — snapshot window, retention depth, point-in-time recovery to an arbitrary moment, copies in a backup region.
  • Recovery procedure — a step-by-step scenario for restoring from a copy with validation in a separate environment and a target time to return to service.
  • Set of metrics and alerts — which thresholds count as a problem, who receives the signal, and what to do for each scenario.
  • Runbooks for typical operations — changing the instance class, upgrading a major version, and testing failover to the standby node.

The documentation lives in the repository next to the configuration and is updated in the same change as the code. That way it does not diverge from the actual state of the infrastructure a month after delivery.

Case study: a production database stopped going down under peak load

Starting point

The production database handled sales and the storefront, but during peak hours response times sagged, and if an Availability Zone failed, recovery was manual.

Storage was allocated "by eye," and once every one or two months the nightly export hit the limit — writes stopped until the volume was expanded.

What we changed

We described the infrastructure as code and moved the database to Amazon RDS in Multi-AZ mode: a standby node in a separate Availability Zone and automatic failover without an on-call engineer.

Parameters, maintenance windows, and the backup policy are now changed through review in the repository rather than by hand in the console.

We enabled storage autoscaling with an alert on the fill threshold, a read replica for analytical queries, and snapshot encryption.

Monitoring was tied to four signals — free space, connection count, write latency, replica lag — and each has an owner, not just a chart on a dashboard.

The result

Peak-hour availability rose from 97% to 99.95%, and failover on a zone failure fits within a minute. Storage overflow incidents are now zero instead of one or two per month: the volume expands on its own, and the warning arrives well before the threshold.

Analytical exports moved to the replica, so heavy reports no longer compete with order intake for resources. We validate the recovery procedure against a snapshot: we bring up a point in time and confirm that the rollback fits within the agreed window.

How a managed database differs from a database on your own servers

The choice between a managed database and servers in your own rack is first and foremost a question of where the provider's responsibility ends.

A managed service like Amazon RDS takes on the hardware, disk failure, engine updates, backups, and failover to a standby node in another Availability Zone.

What remains with you is the data schema, indexes, access rights, load, and the application's readiness for a brief connection drop.

This gap is the most commonly underestimated. A failover takes tens of seconds, the database is available afterwards, but an application with long-lived connections and unfinished transactions breaks before the infrastructure does.

That is why configuration still includes connection re-establishment, retryable operations, and a check that no write was lost during failover.

Your own servers give full control over engine parameters, extensions, data placement, and network topology — this is justified for non-standard requirements.

The price of that control is the entire list of work on your side: setting up replication, regularly testing restore from copies, security updates, monitoring disk space, and investigating lock contention.

Database maintenance on a managed service does not disappear — it shifts. Watching table growth, query plans, connection hold times, the parameter change procedure, and rights reviews still stay with you.

The difference is that instead of emergency callouts you do configuration and scheduled checks, while the provider's area of responsibility covers the class of failures that used to require manual intervention.

The practical criterion is simple. If the requirements fit within standard fault-tolerance modes and predictable availability matters more than access to the server itself, the managed option wins on operational effort.

If you need unsupported extensions or have strict data placement requirements, factor in owning your own servers along with on-call rotations and updates.

Common technical doubts before starting work

Doubts before starting rarely concern architecture — they are usually about operations: what happens at the moment of failover, whether the application code will need changes, how the backup volume will behave, and what happens when maintenance is handed over. Below are answers to what customer engineering teams most often check.

Will failover to the standby cause downtime?

If the database is deployed across multiple Availability Zones, the standby node is kept in synchronous replication, and if a node or an entire zone fails, failover happens automatically.

The application reconnects to the same address — we configure retry of a broken connection at the driver level in advance, so the drop does not turn into a manual incident investigation.

Will the application have to be rewritten for read replicas?

No. Replicas are connected via a separate address, and reports, exports, and analytics go there, while the primary node stays on transactions. Only the connection configuration for read scenarios changes in the code; the write logic is untouched.

Will the backup volume grow indefinitely?

No. The retention policy sets the depth and frequency of snapshots, automatic copies older than the retention period are deleted, and long-lived ones are moved to separate storage and enabled on demand. The volume stops growing linearly, while recovery to the required point remains possible.

How does the maintenance handover work?

The infrastructure is described as code and lives in the repository: configuration, access rules, alerts, and backup policies.

We hand over the state, access via roles, the schema, and instructions — the receiving team spins up an identical stand without verbal agreements or hidden manual steps.

Let's discuss the task and come back with a plan and timeline estimate

To come back with a work plan and a realistic timeline estimate rather than generic wording, we need a snapshot of the current state.

Describe the task in your own words: which service you are moving to a managed database, what load profile you expect, and what matters most — availability, read latency, or recovery time.

The inputs used to estimate the scope of work:

  • current database parameters: engine and its branch, instance class, Multi-AZ mode, number of read replicas;
  • network layout: VPC, subnets, security groups, who connects to the database and from where;
  • how the database lives today: manual edits in the console or configuration managed by Terraform, and where state is stored;
  • fault-tolerance requirements: target recovery time, acceptable data loss, maintenance windows;
  • what is already connected to monitoring: which metrics are captured, where alerts go, who responds to them;
  • constraints: environment separation, the procedure for engineers accessing production data, regulations.

In response we send a staged work plan: the scope of work at each step, dependencies between them, a timeline estimate, and the points where your confirmation is needed. We separately mark out what we do, what is required from your team, and by which checks we accept the result.

We are ready to discuss the task concretely — describe it in free form, and we will come back with a plan.