Development and test databases: the quiet half of your database bill
Non-production databases often outnumber production ones five to one and run identical configurations. Scheduling, sizing, and sharing them typically cuts that spend by 70 to 85 percent with no impact on anyone's work.
Quick answer
Non-production databases commonly account for 25 to 40 percent of total database spend because they are cloned from production modules and left running around the clock. Four changes capture most of the saving: stop instances outside working hours (RDS instances can be stopped for up to 7 days, saving roughly 70 percent of compute on a weekday-only schedule), disable Multi-AZ in non-production (a straight 50 percent cut), size down aggressively since correctness testing does not need production memory, and cut backup retention to 0 or 1 day. A fleet of twenty non-production databases on db.m6g.large with Multi-AZ costs about $4,520 per month; the same fleet scheduled, single-AZ, and on db.t4g.medium costs about $350.
Production database cost gets scrutiny because it appears in capacity planning conversations. Non-production database cost gets none, because each individual instance is small and nobody owns the aggregate. Then you count them and find thirty-eight databases across development, staging, QA, demo, and feature branches, most of them copies of a production module with the production settings intact.
Where the money goes
| Setting inherited from production | Non-production cost impact |
|---|---|
| Multi-AZ enabled | 2x compute and storage |
| Instance sized for production load | 4x to 16x more than needed |
| Running 730 hours per month | 4x more than working hours require |
| 35 day backup retention | Backup storage overage |
| Provisioned IOPS | $0.10 per IOPS-month for test data |
| Cross-region backup copies | Duplicate storage plus transfer |
These compound multiplicatively. A db.r6g.xlarge with Multi-AZ, 500 GB, and 35 day retention costs about $1,043 per month. The same workload for testing purposes on a scheduled db.t4g.medium, single-AZ, 100 GB, 1 day retention, costs about $18. That is a 58-fold difference on a single environment.
Scheduling is the biggest single lever
A working-hours schedule of 12 hours a day, 5 days a week is 260 hours per month against 730, a 64 percent reduction. A tighter 10 hours by 5 days is 217 hours, 70 percent. On RDS you can stop an instance for up to 7 consecutive days, after which it automatically starts again, so the schedule needs to restart it weekly regardless; a Friday-evening stop and Monday-morning start satisfies that naturally.
| Schedule | Hours/month | db.m6g.large cost | Saving |
|---|---|---|---|
| Always on | 730 | about $114 | baseline |
| Weekdays 07:00 to 21:00 | about 304 | about $48 | 58 percent |
| Weekdays 08:00 to 19:00 | about 239 | about $37 | 67 percent |
| On demand, started by CI when needed | about 60 | about $9 | 92 percent |
Note that stopped RDS instances still bill for storage and for any manual snapshots, so a stopped instance is not free. A 500 GB gp3 volume on a stopped instance is still $57.50 per month, which is why sizing non-production storage down matters as much as scheduling compute.
Do you need production-sized test data?
Usually not. Correctness testing needs representative data shapes, not representative volumes. A 20 GB subset with the same schema, the same foreign key relationships, and the same edge cases catches virtually every bug that a 2 TB copy would, at 1 percent of the storage. Reserve a full-size copy for the specific purposes that need it: performance testing, migration rehearsal, and query plan validation, and run that copy only during the window when the testing happens.
Subsetting also removes a compliance burden. A development database populated from a production dump carries real customer data into an environment with weaker access controls, which is a risk most teams would rather not hold. Generated or masked subsets solve the cost problem and the privacy problem at the same time.
Sharing instead of cloning
Per-developer and per-feature-branch databases are convenient and expensive. Two patterns reduce the count without reducing the convenience. First, schema-per-branch on a single shared instance: each branch gets its own schema or database within one PostgreSQL instance, so twenty branches share one db.t4g.medium at $50 per month instead of twenty instances at $1,000. Second, ephemeral databases created by CI at the start of a test run and destroyed at the end, which cost only the minutes they exist.
| Pattern | 20 branches monthly |
|---|---|
| One db.t4g.medium per branch, always on | about $1,000 |
| One db.t4g.medium per branch, scheduled | about $330 |
| Schema-per-branch on one shared instance | about $50 |
| Ephemeral, created per CI run | about $15 |
Make it structural
The reason non-production cost drifts back is that it is controlled by defaults in a module. Fix it there: make multi_az, instance_class, allocated_storage, backup_retention_period, and the schedule all driven by an environment variable, with non-production defaults that are deliberately small. Then a developer copying the module into a new environment gets the cheap configuration automatically and has to make an explicit decision to get an expensive one.
Add a tag requirement for an owner and an expiry date on every non-production database, and a scheduled job that reports databases past their expiry. Most of the waste in a mature account is not any single bad decision, it is environments created for a project that finished eighteen months ago.
Price non-production configurations from Terraform so the environment defaults are visible in review. Compare instance and storage options against the resource catalog, and see database right-sizing for the sizing method.
FAQ
How much of database spend is non-production?
Commonly 25 to 40 percent, because non-production databases usually outnumber production ones and are cloned from production modules with production settings intact. A fleet of twenty non-production databases on db.m6g.large with Multi-AZ costs about $4,520 per month; the same fleet scheduled to working hours, single-AZ, and on db.t4g.medium costs about $350.
How much does scheduling non-production databases save?
A weekday 07:00 to 21:00 schedule is about 304 hours a month against 730, a 58 percent compute saving. A tighter 08:00 to 19:00 schedule is about 239 hours, 67 percent. Databases started on demand by CI can run as little as 60 hours a month, 92 percent. Note RDS allows stopping an instance for up to 7 consecutive days, so a weekly restart is required regardless.
Is a stopped database free?
No. Stopped RDS instances still bill for storage and for any manual snapshots. A 500 GB gp3 volume on a stopped instance is still $57.50 per month. That is why sizing non-production storage down, typically to a small representative subset, matters as much as scheduling the compute off.
Do test databases need production-sized data?
Rarely. Correctness testing needs representative data shapes, not representative volumes: a 20 GB subset with the same schema, foreign key relationships, and edge cases catches virtually every bug a 2 TB copy would, at 1 percent of the storage. Keep full-size copies only for performance testing, migration rehearsal, and plan validation, and run them only during those windows.
What is the cheapest pattern for per-branch databases?
Schema-per-branch on one shared instance, where twenty branches share a single db.t4g.medium at about $50 per month instead of twenty instances at about $1,000. Ephemeral databases created by CI at the start of a test run and destroyed at the end are cheaper still, around $15 per month, since they cost only the minutes they exist.
How does C3X help control non-production database cost?
C3X prices database configuration from Terraform in the pull request, so environment defaults for multi_az, instance_class, allocated_storage, and backup retention carry visible figures at review time. Since non-production waste comes from production settings copied into a module rather than from any single decision, catching the inherited configuration at review is where it is cheapest to fix.
What to do next
Give non-production databases defaults that are cheap by design. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.
Share this post
Try C3X on your own Terraform
Free and open source. No API key required. One command to install, one command to estimate.