Skip to content

Upgrade RDS PostgreSQL from 13 to 15 - #152

Merged
ale210 merged 2 commits into
mainfrom
150-upgrade-rds-postgres-15
Aug 11, 2026
Merged

Upgrade RDS PostgreSQL from 13 to 15#152
ale210 merged 2 commits into
mainfrom
150-upgrade-rds-postgres-15

Conversation

@ale210

@ale210 ale210 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Closes #150.

Upgrades the shared incubator-prod-database instance from PostgreSQL 13.20 to 15. 13.20 is deprecated and the instance is on paid RDS Extended Support.

Changes, all in terraform/database.tf

  • Add aws_db_parameter_group.postgres15 (family = "postgres15") and point parameter_group_name at it. RDS rejects a major upgrade that keeps an old-family group, and default.postgres15 does not exist in the account — AWS creates default groups lazily, and default.postgres13 is currently the only one.
  • allow_major_version_upgrade = true. Absent today; the apply fails outright on a major bump without it.
  • engine_version "13.20""15". Major only: auto_minor_version_upgrade = true is already set, so pinning a full minor would guarantee drift the next time AWS patches.
  • option_group_name "default:postgres-13""default:postgres-15". Same family constraint.
  • Remove the import block. It was the one-time adoption of the pre-existing instance and has already run.

Left deliberately unchanged, per decisions recorded on #150: engine_lifecycle_support stays open-source-rds-extended-support, apply_immediately stays true, and password_encryption is unset so the engine default (scram-sha-256) applies to roles created after the upgrade.

The file's existing wide = alignment is preserved. terraform fmt wants to reformat this file, but it did so before this branch as well — all six .tf files in the directory are unformatted at main. Reformatting is left out of scope so the change stays reviewable.

Before merging

Confirm the terraform-plan output is an in-place update to aws_db_instance.default. A plan proposing to replace this resource must not be merged — skip_final_snapshot = true and deletion_protection = false mean nothing would stop a destroy of the shared database.

Merging is the deploy. .github/workflows/terraform-apply.yaml runs terraform apply with auto_approve: true on every push to main touching a .tf file, and apply_immediately = true means the upgrade begins on merge rather than deferring to the maintenance window. Expect roughly 10-20 minutes of downtime on this data volume.

Prerequisites already completed

  • Automated backups and baseline snapshot (Enable automated backups and take a baseline snapshot on the shared RDS instance #149). backup_retention_period = 4 is in effect and incubator-prod-database-pre-pg15 exists.
  • PostGIS extension registration. ballotnav_db_dev and ballotnav_db_prod registered PostGIS 3.0.2 while the instance loads 3.4.3 — an RDS minor patch had replaced the binaries without ALTER EXTENSION ... UPDATE ever being run. PG15 on RDS has no 3.0.2, so pg_upgrade would have failed after taking the instance down. Both databases are now at 3.4.3 with the registered version matching the loaded library. Details in the pre-flight comment on Upgrade shared RDS PostgreSQL from 13 to 15 #150.

Pre-flight also confirmed no logical replication slots and no reg* columns in any database, both of which would have blocked pg_upgrade.

After merging

Post-merge verification is tracked on #150 and cannot be done from this branch. The most commonly missed step is ANALYZE on every database — pg_upgrade does not carry optimizer statistics across, so query plans will be poor until it runs.

ale210 and others added 2 commits August 10, 2026 17:32
Adds a postgres15 parameter group, enables major version upgrade, and
moves the option group to the postgres-15 family. Removes the stale
import block, which already ran.
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Terraform plan in terraform
With backend config files: terraform/prod.backend.tfvars

Plan: 1 to add, 1 to change, 0 to destroy.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+   create
!~  update in-place

Terraform will perform the following actions:

  # aws_db_instance.default will be updated in-place
!~  resource "aws_db_instance" "default" {
+       allow_major_version_upgrade           = true
!~      engine_version                        = "13.20" -> "15"
        id                                    = "db-WEFHC5MZIA5NX5PBTQZPC2STZQ"
!~      option_group_name                     = "default:postgres-13" -> "default:postgres-15"
!~      parameter_group_name                  = "default.postgres13" -> "incubator-prod-postgres15"
        tags                                  = {
            "Name"              = "incubator-prod-database"
            "terraform_managed" = "true"
        }
#        (70 unchanged attributes hidden)
    }

  # aws_db_parameter_group.postgres15 will be created
+   resource "aws_db_parameter_group" "postgres15" {
+       arn          = (known after apply)
+       description  = "incubator-prod-database, PostgreSQL 15"
+       family       = "postgres15"
+       id           = (known after apply)
+       name         = "incubator-prod-postgres15"
+       name_prefix  = (known after apply)
+       region       = "us-west-2"
+       skip_destroy = false
+       tags         = {
+           "Name"              = "incubator-prod-postgres15"
+           "terraform_managed" = "true"
        }
+       tags_all     = {
+           "Name"              = "incubator-prod-postgres15"
+           "managed-by"        = "terraform-incubator"
+           "terraform_managed" = "true"
        }
    }

Plan: 1 to add, 1 to change, 0 to destroy.

❌ Error applying plan in Terraform apply (OIDC) #60

@ale210
ale210 merged commit 2711e86 into main Aug 11, 2026
2 checks passed
@ale210
ale210 deleted the 150-upgrade-rds-postgres-15 branch August 11, 2026 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade shared RDS PostgreSQL from 13 to 15

1 participant