# Aurora serverless — Worked Examples and Scale-to-Zero Rules Companion to [instructions.md](serverless-advisory-instructions.md) and [formulas-and-examples.md](serverless-advisory-formulas-and-examples.md). The formulas and pricing tables used to produce these numbers live in [formulas-and-examples.md](serverless-advisory-formulas-and-examples.md). ## Worked example — basic sizing User asks: db.r6g.xlarge, CPU P95 35%, max 72%, 500 GiB storage, should I switch to Aurora serverless? Region: us-east-1. Agent reply should follow this pattern — present the script output, no derivation shown: > "Loading `references/serverless-advisory-instructions.md` — this is the serverless sizing workflow. > > The command to run this analysis yourself from a machine with Python 3.10+ and boto3 installed: > > ```bash > python3 scripts/acu_calculator.py estimate \ > --instance db.r6g.xlarge --cpu-p95 35 --cpu-max 72 --storage 500 --region us-east-1 > ``` > > Running that with your parameters produces: > > | Metric | Value | > |---|---| > | min ACU | 3.5 | > | max ACU | 16.0 | > | typical ACU | 6.0 | > | Peak ACU vs 256 ceiling | Well under (12.0/256) | > > | Monthly cost | Amount | > |---|---| > | Provisioned db.r6g.xlarge compute | $379 | > | Aurora serverless at typical ACU compute | $526 | > | Aurora serverless total range (min–max, incl. storage) | $357–$1,452 | > | Storage (500 GiB × $0.10) | $50 | > | **Total Provisioned / Total Aurora serverless (typical)** | **$429 / $576** | > > **Recommendation: not_recommended.** At typical load, Aurora serverless is ~34% more expensive than provisioned ($576 vs $429). Your workload (P95 35%, max 72%) is steady — the burst/idle pattern that makes serverless win isn't present. Stay on db.r6g.xlarge. If you want the savings anyway, consider a 1-year RI on the provisioned instance (~30% off compute), which brings total to ~$315/mo." Note what this reply does NOT include: no "0.21 × 4 × 4 = 3.36, round up to 3.5" arithmetic; no formula derivation; no "here's how I computed it." Just the script-style output. (The internal formulas for producing these numbers are in [formulas-and-examples.md](serverless-advisory-formulas-and-examples.md). Use them to generate the output, but don't copy them into the reply.) ## Worked example — migration with connection and working-set constraints User: db.r7g.2xlarge, 200 peak connections, 12 GiB working set, P95 40%, max 65%, 1 TB storage, region eu-west-1. Walk through the whole thing. Agent response pattern (abridged): 1. Announce reference: "Loading `references/serverless-advisory-instructions.md`." 2. Print: ```bash python3 scripts/acu_calculator.py estimate \ --region eu-west-1 \ --instance db.r7g.2xlarge \ --cpu-p95 40 --cpu-max 65 \ --connections 200 --working-set 12 --storage 1000 \ --num-instances 1 --format table ``` 3. Script output (db.r7g.2xlarge, 8 vCPU): min_ACU **8.0** (working-set floor 12/2 = 6.0 is satisfied), peak_ACU **21.0**, max_ACU **27.5** (= max(round_up(21.0 × 1.30), round_up(13.5 × 1.50))), typical_ACU **13.5**. 4. Costs: offline/static mode prices at **us-east-1 rates** ($0.12/ACU-hr, $0.10/GiB-mo storage) regardless of `--region`; only live API mode applies the eu-west-1 rate. Aurora serverless typical 13.5 × $0.12 × 730 = **$1,183/mo compute**, storage 1000 × $0.10 = $100, total**$1,283/mo**. Provisioned r7g.2xlarge: $1.106 × 730 = $807 + $100 = **$907/mo**. Recommendation: **not_recommended** — serverless is ~41% more at this steady load. 5. Memory advisory: your 12 GiB working set means **min_ACU MUST be ≥ 6.0** to keep the hot set in memory. min_ACU=8 already satisfies this. If you set min below 6 you will see buffer-cache misses. 6. Migration approaches: - **In-place** (`modify-db-cluster --serverless-v2-scaling-configuration`): simplest, fastest; brief restart per instance. Caveats: cluster must already be r6+ generation. - **Blue/Green** (recommended for production): new Aurora serverless writer built as green environment, tested under live replication, switchover in <1 min. Best rollback path. - **Snapshot restore to a new cluster**: full rebuild; longest, but gives you a parallel cluster to test end-to-end. 7. Parameter group: MUST be an Aurora serverless-compatible parameter group (family `aurora-mysql8.0`). DO NOT hardcode `innodb_buffer_pool_size` (Aurora resizes it with ACU) or `max_connections` (Aurora derives it from the cluster's maximum ACU; it is static and needs a reboot to change). Override only for well-understood special cases. 8. CloudFormation snippet (Aurora serverless writer): ```yaml ClusterParameterGroup: Type: AWS::RDS::DBClusterParameterGroup Properties: Family: aurora-mysql8.0 Description: Enforce TLS for Aurora serverless cluster Parameters: require_secure_transport: "ON" DBCluster: Type: AWS::RDS::DBCluster Properties: Engine: aurora-mysql EngineVersion: "8.0.mysql_aurora.3.08.0" DBClusterParameterGroupName: !Ref ClusterParameterGroup ServerlessV2ScalingConfiguration: MinCapacity: 8.0 MaxCapacity: 27.5 StorageEncrypted: true EnableCloudwatchLogsExports: - error - slowquery - audit WriterInstance: Type: AWS::RDS::DBInstance Properties: DBInstanceClass: db.serverless Engine: aurora-mysql DBClusterIdentifier: !Ref DBCluster ``` 9. CDK snippet (TypeScript): ```typescript const parameterGroup = new rds.ParameterGroup(this, "PG", { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_08_0 }), parameters: { "require_secure_transport": "ON" }, }); const cluster = new rds.DatabaseCluster(this, "Cluster", { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_08_0 }), parameterGroup, serverlessV2MinCapacity: 8.0, serverlessV2MaxCapacity: 27.5, writer: rds.ClusterInstance.serverlessV2("Writer"), storageEncrypted: true, cloudwatchLogsExports: ["error", "slowquery", "audit"], }); ``` 10. Testing: snapshot-restore to a test cluster first; run full load tests at peak TPS; observe `ServerlessDatabaseCapacity` CloudWatch metric to verify ACU actually scales with load. ## Scale-to-zero / auto-pause rules Aurora serverless auto-pause requires `MinCapacity: 0` and is **incompatible** with: RDS Proxy, binary logging (binlog) enabled, Global Database primary, and Zero-ETL integrations. If the user's workload has any of these, you MUST warn them that scale-to-zero cannot be enabled, and instead recommend a non-zero `MinCapacity` (e.g. 0.5 for dev/test, ≥1.0 for prod). In a multi-AZ cluster, auto-pause still works: the writer and any reader instances with failover priority 0 or 1 pause and resume together (their capacity is tied to the writer), while reader instances with failover priority 2-15 can pause independently. So a reader configured with priority 0/1 will not pause unless the writer also pauses — but the cluster as a whole can still scale to zero. See [concepts.md](serverless-advisory-concepts.md) for the complete compatibility matrix.