ChistaDATA · DBaaS optimisation for RDS, Aurora, Cloud SQL, AlloyDB and Azure Database, with 24×7 support

DBaaS optimisation is the engineering discipline of reading a managed-database bill as a set of meters, tracing each meter back to the SQL statements and schema decisions that drive it, and changing those before touching the instance. ChistaDATA delivers it as an evidence-led assessment, hands-on engineering on your PostgreSQL and MySQL-family DBaaS, and 24×7 consultative support or managed services that keep the bill from drifting back.

This page sets out the method at engineering depth: the cost anatomy of a statement on RDS, Aurora, Cloud SQL and Azure Database; the catalog and provider telemetry the assessment is built from; the five levers applied in a fixed order; the architectural option of moving analytical reads to ClickHouse; and the FinOps cadence and guardrails that hold the result.

4Meters every DBaaS bill reduces to: compute, I/O, storage and backup, data transfer
5Levers, applied in order: SQL and indexes, connections, storage class and instance, architecture, autoscaling governance
15 minSeverity 1 response for DBaaS optimisation support customers, 24×7×365
0Instance changes made before the top statement fingerprints are fixed and re-measured

Cost anatomy

What DBaaS optimisation is actually optimising: four meters and the statements behind them

A managed database moves the cost of inefficiency from a capital line to a monthly one. On a fixed on-premises server, a query that scans a table it should have indexed costs latency; on Amazon RDS, Aurora, Google Cloud SQL, AlloyDB or Azure Database for PostgreSQL and MySQL, the same query is metered. Every DBaaS bill, whatever the provider’s naming, reduces to four meters: compute (instance hours, vCores or Aurora Serverless v2 ACU-seconds), I/O (provisioned IOPS, io2 throughput, Aurora Standard I/O requests), storage and backup (GB-month for volumes, snapshots and log retention), and data transfer (cross-AZ replication, egress to clients, cross-region replicas).

Each of those meters is driven by a metric the engine already exposes. CPU is driven by execution time per statement fingerprint; I/O by buffer misses (shared_blks_read in PostgreSQL, Innodb_buffer_pool_reads in MySQL); storage by bloat, dead tuples, index bytes and WAL or binlog volume; transfer by result-set size and replica placement. DBaaS optimisation is the act of joining the two views and then working on the statements, because that is where the meter is actually set.

DBaaS optimisation cost anatomy: how one SQL statement becomes compute, I/O, storage and data-transfer bill lines on RDS, Aurora, Cloud SQL and Azure Database
Fig. 1 — DBaaS optimisation cost anatomy. One unindexed statement executed 1,400 times an hour drives all four meters; the engine metric that decides each bill line is named on the right.
Bill lineHow the providers meter itThe engine metric that moves it
ComputeRDS and Cloud SQL instance class hours; Aurora Serverless v2 ACU-seconds; Azure vCore hourstotal_exec_time per fingerprint, DBLoad (Performance Insights), CPU p95, parallel workers launched
I/Ogp3 and io2 provisioned IOPS and throughput; Aurora Standard I/O requests versus I/O-Optimized; Cloud SQL disk IOPS; Azure premium SSD tiershared_blks_read, buffer hit ratio, Innodb_buffer_pool_reads, ReadIOPS, WriteIOPS, queue depth
Storage and backupAllocated GB-month; automated backup beyond the free window; manual snapshots; PITR and log retentionTable and index bytes, n_dead_tup, bloat ratio, WAL bytes per hour, snapshot size, retention days
Data transferCross-AZ replication and reader traffic; egress to clients; cross-region and Global Database replicationResult rows per statement, replica lag bytes, reader placement versus application AZ, logical slot traffic
Figures on this page (execution counts, sizes, durations) are illustrative worked examples, not benchmark claims; every number that matters is measured on your own estate during the assessment. Provider pricing models change; ChistaDATA confirms the current metering for your account and region before any recommendation is costed. Test every change on a staging instance or a restored snapshot before production, and maintain a tested backup and DR posture throughout.

Evidence

The DBaaS optimisation evidence pack: catalog views and provider telemetry, read together

The assessment starts with seven days of engine telemetry placed next to seven days of bill lines. On PostgreSQL-family services the core source is pg_stat_statements, which RDS, Aurora, Cloud SQL and Azure all expose, joined to pg_stat_user_tables, pg_stat_user_indexes and, on PostgreSQL 16+, pg_stat_io. On MySQL-family services it is performance_schema.events_statements_summary_by_digest and the sys schema views. Provider layers add per-statement load over time: Performance Insights on RDS and Aurora, Query Insights on Cloud SQL and AlloyDB, Query Store on Azure Database for PostgreSQL.

-- DBaaS optimisation evidence, PostgreSQL 15+ (RDS, Aurora, Cloud SQL, AlloyDB, Azure): rank fingerprints by the meter they drive
SELECT queryid,
       calls,
       round(total_exec_time::numeric / 1000, 1)                       AS total_s,
       round(mean_exec_time::numeric, 2)                               AS mean_ms,
       shared_blks_read + shared_blks_written + temp_blks_written      AS io_blocks,
       round(100.0 * shared_blks_hit / greatest(shared_blks_hit + shared_blks_read, 1), 1) AS hit_pct,
       rows,
       left(query, 90)                                                 AS sample
FROM pg_stat_statements
WHERE dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
ORDER BY io_blocks DESC          -- I/O meter first; re-run ORDER BY total_exec_time DESC for the compute meter
LIMIT 20;

-- Unused indexes: paid for on every write as WriteIOPS and WAL bytes, never read
SELECT schemaname, relname, indexrelname, idx_scan,
       pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE idx_scan = 0 AND indexrelname NOT LIKE '%_pkey'
ORDER BY pg_relation_size(indexrelid) DESC;
-- DBaaS optimisation evidence, MySQL 8.0 / 8.4 (RDS, Aurora MySQL, Cloud SQL, Azure Database for MySQL)
SELECT DIGEST_TEXT,
       COUNT_STAR                                   AS calls,
       ROUND(SUM_TIMER_WAIT / 1e12, 1)              AS total_s,
       SUM_ROWS_EXAMINED / GREATEST(SUM_ROWS_SENT, 1) AS examined_per_row_sent,
       SUM_NO_INDEX_USED,
       SUM_CREATED_TMP_DISK_TABLES
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_ROWS_EXAMINED DESC
LIMIT 20;

SELECT * FROM sys.schema_unused_indexes;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';   -- reads vs read_requests: the I/O meter in two counters

The output of this phase is one ranked list of statement fingerprints, each tagged with the meter it drives and its share of that meter. That list is the artefact the whole DBaaS optimisation engagement is organised around: it decides what is engineered first, it is what the verification phase re-measures, and it is what the quarterly review carries forward.

Method

The DBaaS optimisation loop: measure, rank, engineer, verify, hold

The order of operations is the method. Instances are never downsized first, because the same work then lands on fewer cores, p95 rises, and either autoscaling or an incident restores the cost within a week. Statements are fixed first, storage class second, instance class and commitments last, and every step has an exit gate that is a measurement rather than an opinion.

The DBaaS optimisation loop ChistaDATA runs: measure, rank, engineer, verify and hold, with exit gates and owners per step
Fig. 2 — The DBaaS optimisation loop. Five steps with exit gates and owners; the loop re-runs every quarter because releases add fingerprints, data grows and provider pricing changes.

Two rules apply across all five steps. First, every change to a production database is staged on a replica or a restored snapshot, applied in a window, and recorded with its previous value and its rollback path, whether it is an index, a parameter-group change or an instance class. Second, the meter is what is verified, not the latency: a statement that got faster but still reads the same blocks has not reduced the I/O bill, and a right-size is approved only when the meter delta has held for seven days.

Lever 1

DBaaS optimisation at the statement: SQL rewrites and index engineering with plan evidence

Most of the compute and I/O meter is usually explained by a small number of fingerprints, and most of those are fixed by an index that matches the predicate and the sort, a rewrite that removes a correlated subquery or a SELECT *, or a partial or covering index that lets the executor answer from the index alone. The proof for every change is the plan with buffers, before and after, on a staging copy with production statistics.

-- Before: the Fig. 1 statement on a 400 GB orders table (illustrative), PostgreSQL 16 on Aurora
EXPLAIN (ANALYZE, BUFFERS, SETTINGS)
SELECT c.segment, count(*), sum(o.total)
FROM orders o JOIN customers c USING (customer_id)
WHERE o.created_at >= now() - INTERVAL '90 days' AND c.region = 'EMEA'
GROUP BY c.segment;
-- Parallel Seq Scan on orders ... Buffers: shared hit=212,410 read=3,948,117  (I/O meter: ~30 GB read per execution)

-- DBaaS optimisation change set (staged, then applied CONCURRENTLY in a window)
CREATE INDEX CONCURRENTLY idx_orders_created_at_recent
    ON orders (created_at) INCLUDE (customer_id, total)
    WHERE created_at >= DATE '2026-01-01';          -- partial: only the hot range is indexed and paid for
CREATE INDEX CONCURRENTLY idx_customers_region_segment
    ON customers (region, customer_id) INCLUDE (segment);

-- After: Index Only Scan using idx_orders_created_at_recent ... Buffers: shared hit=48,900 read=1,230
-- Validation: rerun EXPLAIN (ANALYZE, BUFFERS); compare shared read, temp written and execution time per call
-- Rollback: DROP INDEX CONCURRENTLY idx_orders_created_at_recent; (no data change, reversible in one statement)

Indexes are not free on a metered service: each one is written on every INSERT and UPDATE, which shows up as WriteIOPS and WAL or binlog bytes, and it adds to GB-month and to snapshot size. The unused-index query above is run before any index is added, duplicate and overlapping indexes are consolidated, and write amplification is measured on the staging copy using pg_stat_user_tables.n_tup_upd and WAL bytes per hour. Predicates that defeat indexes (functions on columns, implicit casts, leading wildcards) are rewritten in the application with the app team, with the fingerprint’s meter share as the priority.

Lever 2

Connections, pooling and memory: the DBaaS optimisation lever that changes the instance class you need

On PostgreSQL, every connection is a backend process with its own memory, and work_mem is allocated per sort or hash node per query, not per session. An application tier that opens 2,000 connections against an instance sized for 500 forces either an oversized instance class or a steady stream of memory pressure and connection errors. On MySQL, thread and buffer allocations behave similarly. Pooling is therefore a sizing lever, not just a stability one: with PgBouncer in transaction mode, RDS Proxy, Cloud SQL’s managed connection pooling or ProxySQL in front of MySQL, the instance is sized for active sessions rather than for open ones.

ParameterTypical DBaaS defaultDBaaS optimisation postureReload or restart
max_connections (PostgreSQL)Derived from instance memory (RDS: DBInstanceClassMemory/9531392)Cap at measured peak active sessions × 2 behind a pooler; never raise it to absorb application leaksRestart
work_mem4 MBSet per role: higher for reporting roles with few sessions, lower for OLTP roles with many; watch temp_blks_writtenReload (per role: ALTER ROLE ... SET)
idle_in_transaction_session_timeout0 (disabled)60 s to 5 min, so abandoned transactions stop holding locks and blocking vacuumReload
statement_timeout0 (disabled)Per role: seconds for OLTP roles, minutes for reporting; the single most effective cost guardrailReload
innodb_buffer_pool_size (MySQL)~75% of instance memoryKeep; verify Innodb_buffer_pool_reads stays low before any downsize, since the pool shrinks with the classDynamic since 5.7
max_connections (MySQL)Derived from memoryBound by ProxySQL or the application pool; alert on Threads_running, not on Threads_connectedDynamic

Each parameter change is recorded as parameter, current value, proposed value, unit and whether it needs a reload or a restart, and is applied to a staging parameter group first. On Aurora and RDS a restart-class change is scheduled into the maintenance window with a failover to the reader where Multi-AZ allows it, so the application sees seconds rather than minutes.

Lever 3

Storage class, instance class and commitments: the DBaaS optimisation decisions made last, from evidence

Only after the top fingerprints are fixed and the meters have moved for seven days does the assessment turn to the instance. The storage decision comes first because it changes the I/O meter directly: gp3 with baseline IOPS versus provisioned IOPS, io2 for sustained write-heavy workloads, Aurora Standard versus I/O-Optimized (the break-even is a function of the I/O share of the bill, which the evidence pack already contains), Cloud SQL SSD versus Hyperdisk tiers, Azure premium SSD versus v2.

The instance decision follows, from CPU p95 and freeable memory after the change set, never from average CPU. Commitments (reserved instances, committed-use discounts, reserved capacity) are bought last, against the right-sized footprint, so that a one-year commitment is not made for a class the workload no longer needs.

# DBaaS optimisation right-size evidence, captured per instance for 7 days after the change set (illustrative)
instance:                 prod-orders-01 (Aurora PostgreSQL 16, db.r6g.4xlarge)
cpu_p95_before / after:   71% / 34%          # CloudWatch CPUUtilization, 1-minute
read_iops_p95:            18,400 / 2,900     # ReadIOPS; the Fig. 1 statement set is fixed
write_iops_p95:           4,100 / 3,700      # WriteIOPS; one unused index dropped
freeable_memory_min:      9.8 GB / 41 GB     # buffer cache no longer churned by scans
io_share_of_bill:         38% / 11%          # from Cost Explorer, Aurora Standard I/O line
top20_p95_ms:             640 / 95           # pg_stat_statements, same fingerprints
decision:                 db.r6g.2xlarge; stay on Aurora Standard (I/O-Optimized no longer breaks even)
rollback:                 modify-db-instance back to r6g.4xlarge; Multi-AZ failover, ~60 s

Backup and log retention are part of this lever: automated backup retention beyond the free window, manual snapshots that were never pruned, and long PITR windows are GB-month lines that grow with the database. They are set from the recovery objectives in your DR plan, which ChistaDATA reviews in the same assessment, and never silently reduced to save money.

Lever 4

Architectural DBaaS optimisation: caching, partitioning, replicas, and when analytics should leave the managed database

Some statements cannot be made cheap on a row store because they are the wrong shape for it. Dashboards that aggregate months of rows every minute, month-end reports, funnel and cohort queries, and analyst ad-hoc SQL all read wide ranges of a table that the OLTP engine stores row by row and that the provider bills per I/O request. The usual fixes inside the DBaaS (a reporting read replica, a larger instance) move the same work rather than removing it: the replica reads the same blocks and is billed for them, and the primary’s buffer cache is still churned by the scans.

Architectural DBaaS optimisation: OLTP stays on the managed database while reporting and analytics move to ClickHouse through CDC
Fig. 3 — Architectural DBaaS optimisation. Transactions, point reads and constraints stay on the managed database; reporting and analytics move to open-source ClickHouse fed by CDC, and the DBaaS is then sized from its OLTP steady state.

ChistaDATA’s architectural option is to keep OLTP where it is and move the analytical statements to 100% open-source ClickHouse in your own VPC, fed by logical replication through Debezium and Kafka into ReplacingMergeTree tables with materialized views for the aggregates. The application does not change; BI tools are pointed at ClickHouse over the native, MySQL or PostgreSQL wire protocol.

The DBaaS instance is then right-sized from its OLTP steady state, the reporting replica is retired, and the analytical workload runs on fixed compute where concurrency is a sizing decision rather than a meter. The full engineering of that path, including reconciliation and the gated purge of history from the row store, is described on the RDBMS archival and archiving data to ClickHouse pages.

-- ClickHouse 25.x / 26.x LTS target for the offloaded orders facts (explicit engine and parameters)
CREATE TABLE analytics.orders ON CLUSTER '{cluster}'
(
    order_id     UInt64,
    customer_id  UInt64,
    created_at   DateTime64(3, 'UTC') CODEC(DoubleDelta, ZSTD(3)),
    region       LowCardinality(String),
    segment      LowCardinality(String),
    total        Decimal(18, 2)       CODEC(ZSTD(3)),
    _version     UInt64,
    _deleted     UInt8
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{shard}/analytics/orders', '{replica}', _version, _deleted)
PARTITION BY toYYYYMM(created_at)
ORDER BY (region, created_at, order_id)
SETTINGS index_granularity = 8192;

-- The Fig. 1 dashboard statement, now a sort-key-aligned range read on compressed columns
SELECT segment, count(), sum(total)
FROM analytics.orders FINAL
WHERE region = 'EMEA' AND created_at >= now() - INTERVAL 90 DAY
GROUP BY segment;

Inside the DBaaS, two more architectural levers apply before any offload. Partitioning by time on churned tables keeps autovacuum, index sizes and backups bounded and makes retention a DROP PARTITION rather than a metered DELETE. A cache (ElastiCache, Memorystore, Azure Cache) in front of read-heavy point lookups removes repeated reads from the I/O meter entirely; it is justified by the hit ratio the evidence pack predicts, not by habit.

Lever 5

Autoscaling and serverless governance: DBaaS optimisation for Aurora Serverless v2, read-replica autoscaling and storage autoscaling

Autoscaling converts inefficiency into spend without an alert. Aurora Serverless v2 scales ACUs on CPU and memory pressure, so an unindexed report ramps the instance and the bill together; read-replica autoscaling adds readers that execute the same scans; storage autoscaling grows volumes that bloat filled. Governance means bounding each of these from measured need: a minimum ACU that covers the OLTP steady state so cold starts do not hurt p95, a maximum ACU set from the highest legitimate peak in the evidence pack rather than the default, replica scaling policies keyed to DatabaseConnections and CPU on the readers, and storage autoscaling paired with bloat monitoring so growth is a signal, not a silent line.

ServiceWhat scalesWhat DBaaS optimisation bounds it with
Aurora Serverless v2ACUs per instance (0.5 to 256 in 0.5 steps)Min ACU from OLTP steady-state memory; max ACU from measured peak; ServerlessDatabaseCapacity reviewed weekly against fingerprints
Aurora and RDS read replicasReader count via Application Auto ScalingScale on reader CPU p95, not on connections; alert when a scale-out coincides with a new fingerprint
RDS and Cloud SQL storage autoscalingVolume size, upward onlyBloat and dead-tuple alerts before the threshold; retention by partition so growth is explained
Azure Database flexible serverStorage auto-grow; compute tier is manualTier changes from Query Store evidence in the maintenance window; auto-grow paired with growth alerts
Cloud SQL and AlloyDBRead pool node count (AlloyDB), storageRead pool sized from Query Insights per-node load; storage growth reconciled with table bytes monthly

Every scaling event in the evidence window is matched to the fingerprints active at the time. A scale-out that coincides with a release is a regression to send back to the app team with the plan attached; one that coincides with a genuine traffic peak is a sizing input. This distinction is what keeps DBaaS optimisation from becoming a monthly argument about the bill.

Operating model

The DBaaS optimisation cadence: daily, weekly, monthly and quarterly, with guardrails inside the engine

A one-time optimisation project decays: releases add statements, data grows, provider pricing changes, and within two quarters the bill is back. ChistaDATA holds the result with a cadence under 24×7 support or managed services and with guardrails that live inside the engine and the cloud account rather than in a document.

DBaaS optimisation FinOps cadence: daily, weekly, monthly and quarterly activities, engine guardrails and the ChistaDATA 24x7 support plane
Fig. 4 — The DBaaS optimisation cadence and guardrails. Each activity names the metric it reads and the artefact it produces; the guardrails make a bad release visible before it becomes a bill line.
-- DBaaS optimisation guardrails applied per role (PostgreSQL 15+; reload, no restart)
ALTER ROLE app_oltp      SET statement_timeout = '5s';
ALTER ROLE app_oltp      SET idle_in_transaction_session_timeout = '60s';
ALTER ROLE app_reporting SET statement_timeout = '5min';
ALTER ROLE app_reporting SET work_mem = '256MB';          -- few sessions, large sorts
ALTER ROLE app_oltp      SET work_mem = '8MB';            -- many sessions, small sorts
-- Verification: SELECT rolname, rolconfig FROM pg_roles WHERE rolname LIKE 'app_%';

-- MySQL 8.0 / 8.4 equivalents
SET PERSIST max_execution_time = 5000;                    -- ms, SELECT only; per-session override for reporting users
CREATE USER 'app_reporting'@'%' WITH MAX_USER_CONNECTIONS 20 MAX_QUERIES_PER_HOUR 20000;

Budget alerts are set per meter, not per account, so that an I/O line moving 20% week on week opens a ticket while the total is still inside budget. The weekly fingerprint review compares the current top 20 with last week’s and attributes every newcomer to a release or a data change; the monthly service review presents the bill by meter against the baseline with the change log that explains each delta; the quarterly review re-runs the full loop, times a restore and failover drill, and re-examines which statements are now candidates for the ClickHouse offload.

Engagement

How ChistaDATA delivers DBaaS optimisation: assessment, engineering, and 24×7 support or managed services

DBaaS optimisation assessment

Read-only access to catalog views and provider telemetry, seven days of evidence next to the bill, the ranked fingerprint list with meter attribution, and a change set with plan evidence, staging plan and rollback for each item. Delivered as a versioned, branded document.

Engineering

The change set applied with your DBA and application teams: indexes and rewrites, pooling, parameter groups, partitioning, storage and instance changes, autoscaling bounds, and, where the evidence supports it, the ClickHouse offload built and reconciled.

24×7 support and managed services

The cadence above under the standard escalation matrix (S1 15 min, S2 12 h, S3 24 h, S4 48 h): consultative support beside your team, or managed services that own the estate, the cadence, the guardrails and the monthly cost and SLA report end to end.

Engagements cover Amazon RDS and Aurora (PostgreSQL and MySQL), Google Cloud SQL and AlloyDB, and Azure Database for PostgreSQL and MySQL; MariaDB-family services follow the MySQL method. Every engagement starts with the pre-engagement questionnaire so the first conversation is about your fingerprints and your meters rather than about generic best practice. Where the assessment finds that the workload is correctly sized and the bill is what the business genuinely needs, the report says so.

FAQ

DBaaS optimisation questions ChistaDATA is asked most often

How much can DBaaS optimisation save?

It depends entirely on how much of the bill the top fingerprints explain, which the evidence pack measures in the first week. ChistaDATA does not quote a percentage before seeing pg_stat_statements or the digest summary next to the bill; the assessment report states the expected delta per meter, per change, and the verification phase records what was actually achieved.

Why not just downsize the instance and see what happens?

Because the work does not go away. The same scans run on fewer cores and a smaller buffer cache, p95 rises, I/O increases as the cache hit ratio falls, and autoscaling or an incident restores the previous class. The DBaaS optimisation loop fixes statements first so that a downsize holds.

Does this require moving off the managed database?

No. Four of the five levers are applied inside the DBaaS. The ClickHouse offload is an architectural option for analytical statements that a row store cannot serve cheaply; it is recommended only when the evidence pack shows those statements dominate the I/O or compute meter, and the OLTP database stays exactly where it is.

Which services are covered?

Amazon RDS and Aurora for PostgreSQL and MySQL including Serverless v2, Google Cloud SQL and AlloyDB, and Azure Database for PostgreSQL and MySQL flexible servers. The method is the same for self-managed PostgreSQL and MySQL; only the provider telemetry and the metering differ.

How are production changes kept safe?

Every change is staged on a replica or a restored snapshot with production statistics, applied in a window with the previous value and the rollback path recorded, and verified against the meter for seven days. Index builds use CONCURRENTLY or online DDL, parameter changes are grouped by reload versus restart, and nothing that drops or truncates is executed without an explicit confirmation gate in the runbook.

Next step

Bring the bill and the query statistics; ChistaDATA brings the join between them

A DBaaS optimisation assessment from ChistaDATA takes seven days of catalog and provider telemetry next to seven days of bill lines and returns a ranked fingerprint list, a change set with plan evidence and rollback for each item, and a right-size decision that holds. The same engineers apply it with your team and keep it in place under 24×7 support or as the managed team.

Further reading: RDBMS archival with ChistaDATA Fabric · Archiving data to ClickHouse · Data infrastructure for CTOs · pg_stat_statements · MySQL statement digests · Aurora Serverless v2