by datastudy.nl

Field notes for teams running cloud and SaaS FinOps in production

Engineering

Postgres FinOps: from self-managed to serverless, what hosting actually costs

Running Postgres costs from $15 per month on RDS to tens of thousands self-managed. The three levers are right-sizing, storage tiering and connection pooling.

A slope chart comparing Postgres hosting costs across four models: self-managed on EC2 at $2,800 per month, managed RDS at $1,500, Aurora Serverless v2 at $900, and Supabase at $600, with a dotted AI agent optimization line showing a 25 percent reduction in each.
Monthly Postgres cost comparison across hosting models for a mid-size workload, with estimated AI agent optimization savings. Data Today benchmark.

Postgres is free software. Running Postgres is not. The cost of hosting a production Postgres database varies by a factor of 5 to 10 depending on how you run it, where you run it, and whether you pay someone else to manage it or manage it yourself. And with the rise of serverless Postgres (AWS Aurora Serverless v2, Neon, Supabase, Google Cloud SQL), the cost model is shifting from pay-per-instance to pay-per-query, which changes the FinOps equation fundamentally.

The three FinOps levers for Postgres are instance right-sizing, storage tiering and connection pooling. Get these three right and your database cost stays predictable regardless of hosting model. Get them wrong and you will pay for instance capacity you never use, storage that never gets cleaned up, and connections that force you to a larger instance than your actual query load requires.

What are the hosting models, and what do they actually cost?

Self-managed Postgres on EC2 or Kubernetes gives you full control at the cost of full operational responsibility. A 2-vCPU, 8 GB RAM instance (r6g.large, Graviton) costs roughly $85 per month on-demand. But that is just the instance. Production Postgres needs at least two instances (primary and replica) plus EBS storage (gp3, $0.08 per GB-month), backups (snapshots to S3), and a human who knows how to run pg_dump, configure WAL archiving, and recover from a crash. The fully loaded cost, including 20 percent of a database engineer's time, is typically $1,500 to $3,000 per month for a small to mid-size production deployment.

Managed Postgres on RDS eliminates the operational overhead at a 30 to 50 percent premium over the raw instance cost. An db.r6g.large instance (2 vCPU, 16 GB RAM) with Multi-AZ deployment costs roughly $210 per month for the compute plus $0.16 per GB-month for SSD storage. RDS handles backups, patching, failover and point-in-time recovery automatically. For most teams, the premium is worth it: the engineering time saved by not managing Postgres directly exceeds the RDS markup by a wide margin.

Aurora Serverless v2 is AWS's serverless Postgres-compatible offering. You pay in ACU-hours (Aurora Capacity Units), where 1 ACU is roughly equivalent to 2 GB of memory and corresponding CPU. The minimum is 0.5 ACU ($0.06 per ACU-hour, or roughly $22 per month). The maximum is whatever you set. The cost model is fundamentally different from RDS: you pay for actual database activity rather than provisioned capacity. For workloads with variable traffic (bursty web apps, batch processing that runs once a day), Aurora Serverless v2 can be 40 to 60 percent cheaper than a provisioned RDS instance sized for peak load. For workloads with steady, predictable traffic, RDS with Reserved Instances is usually cheaper.

Neon and Supabase are cloud-native serverless Postgres offerings that separate compute from storage. Neon charges per compute hour (starting at $0.024 per compute hour for a 0.25 vCPU, 1 GB RAM compute) plus storage at $0.0004 per GB-hour. Supabase charges per project (starting at $25 per month for the Pro tier with 8 GB of storage and 50 GB of transfer) plus usage-based fees for additional compute and storage. Both offer a generous free tier that covers small projects and development databases.

Horizontal bar chart of Postgres monthly cost by hosting model: self-managed EC2 at $2,800, managed RDS at $1,500, Aurora Serverless v2 at $900, and Supabase at $600
Monthly Postgres cost comparison across hosting models for a mid-size workload. Illustrative. Data Today benchmark.

What are the three levers that pull hardest?

Instance right-sizing is the same pattern as EC2: size for average load, not peak load. The most common Postgres FinOps mistake is running a db.r6g.xlarge (4 vCPU, 32 GB RAM) when a db.r6g.large (2 vCPU, 16 GB RAM) would handle the workload with room to spare. The key metrics to check are CPU utilization (below 60 percent average is comfortable), freeable memory (above 20 percent of total is comfortable), and read/write IOPS (below 80 percent of the volume's provisioned IOPS is comfortable). RDS Performance Insights surfaces all three in a single dashboard.

The counterintuitive part is that a larger instance is not always faster for Postgres. Postgres can only use one CPU core per query. If your workload is dominated by many small queries, more cores help (parallel execution across queries). If your workload is dominated by a few large queries, more memory for cache helps more than more CPU cores. Rightsizing for Postgres means understanding your query patterns, not just your aggregate utilization metrics.

Storage tiering for Postgres is about more than the $0.08 per GB-month base rate. RDS storage has three dimensions: allocated storage (what you pay for, whether you use it or not), actual data size, and snapshot storage. The gap between allocated and actual is waste: if you allocated 500 GB but only use 120 GB, you are paying for 380 GB of empty space every month. RDS auto-scaling (enabled by default) grows storage when free space drops below a threshold, but it never shrinks it back.

The storage optimization playbook: set a maximum storage limit to prevent runaway auto-scaling, monitor actual versus allocated storage monthly, and for Aurora, enable backtrack (point-in-time rollback) only for the retention period you actually need. Backtrack keeps log records that consume storage. A 72-hour backtrack window on a high-write database can add 10 to 20 percent to your storage cost.

Connection pooling is the least obvious lever. Postgres creates a new process for every database connection, and each process consumes memory (typically 5 to 10 MB). A thousand idle connections consume 5 to 10 GB of memory that could be used for query cache. If your application opens a connection per request and you handle 500 concurrent requests, you need either a connection pooler (PgBouncer, RDS Proxy) or a much larger instance.

RDS Proxy ($0.015 per vCPU-hour) is a managed connection pooler that sits between your application and your database. It multiplexes thousands of application connections onto a smaller number of database connections, reducing memory pressure and allowing a smaller instance size. The proxy typically pays for itself by allowing a one-tier-smaller RDS instance. An application that otherwise needs a db.r6g.xlarge (4 vCPU, 32 GB RAM) to handle connection load might run comfortably on a db.r6g.large (2 vCPU, 16 GB RAM) with the proxy, saving roughly $105 per month.

What changes when you move to serverless?

Serverless Postgres changes the cost model from pay-per-instance to pay-per-query. This is good for variable workloads and potentially dangerous for steady workloads where you forget to set a maximum capacity limit.

With RDS, you know exactly what your database will cost each month: the instance price plus the storage price. With Aurora Serverless v2, your cost depends on how many queries you run and how much CPU they consume. A sudden spike in traffic (a product launch, a marketing campaign, a DDoS attack) increases your database bill in real time. Setting a maximum ACU limit is the equivalent of a budget alert on Snowflake: it caps your cost but may throttle performance during a spike.

The serverless model also changes the optimization strategy. On RDS, you optimize by picking the right instance size and committing to a Reserved Instance. On Aurora Serverless, you optimize by reducing query load: better indexes, more aggressive caching, query rewriting, and connection pooling. The database bill becomes a direct reflection of application efficiency, which is both empowering and exposing.

How do AI agents fit into Postgres FinOps?

AWS has not released a Postgres-specific FinOps agent, but the general AWS FinOps Agent can query RDS and Aurora metrics through CloudWatch and Cost Explorer. The highest-ROI agent use cases for Postgres are rightsizing recommendations, unused instance detection (RDS instances or Aurora clusters with zero connections for 14 days), and index recommendation generation.

An agent that can query pg_stat_statements (or RDS Performance Insights) and identify the top 10 slowest queries, their execution count, and their average latency can generate a prioritized list of indexing and query optimization tasks. This is not strictly a FinOps task, but it has a direct cost impact: faster queries need less instance capacity, and less capacity costs less money.

The emerging pattern is an agent that combines cost data (from Cost Explorer) with performance data (from RDS Performance Insights and pg_stat_statements) to answer the question "how much would we save if we optimized these three queries?" An engineer can make the case for spending a day on query optimization by showing the dollar impact. The agent does the math.

Where do you start?

Start with a cost and performance audit of your three most expensive Postgres instances. For each one, check CPU utilization, memory utilization, storage allocated versus used, and connection count. If CPU is below 40 percent, test a one-tier-smaller instance in a staging environment. If storage allocated is more than 2x storage used, file a support ticket with AWS to shrink it (RDS does not support shrinking through the console). If connection count is above 200 and you are not using a connection pooler, evaluate RDS Proxy or PgBouncer.

Then look at your backup retention. RDS automated backups are retained for a configurable number of days (default 7, maximum 35). Every day of retention costs storage. If you also take manual snapshots, check whether any snapshots are older than your retention policy and delete them. Snapshots are incremental in Aurora but full in RDS, so a 500 GB manual RDS snapshot costs the full 500 GB of storage for as long as it exists.

For the broader FinOps lifecycle and where agents fit across platforms, see the overview. The AWS guide covers the AWS FinOps Agent that can query RDS and Aurora metrics, and the Snowflake guide covers the equivalent for data warehouse credits.

Sources