How Do I Migrate an Amazon RDS Parameter Group to a New Engine Version or Aurora Using AWS CLI?
This guide provides an AWS CLI and Bash script using jq to automate parameter group migration across all RDS engines — including PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, and Aurora.
Overview
Issue Popularity
Migrating database parameter group settings is one of the most common operational tasks engineers face when performing:
- Engine version upgrades (e.g., RDS MySQL 5.7 → 8.0, PostgreSQL 14 → 15)
- Migration to Aurora (e.g., RDS MySQL → Aurora MySQL 3, RDS PostgreSQL → Aurora PostgreSQL)
- Cross-region disaster recovery setup (copy parameter group to another region)
Without automation, engineers must manually identify, compare, and re-apply every modified parameter to the new group — a process that is tedious, error-prone, and time-consuming, especially for databases with hundreds of customized parameters.
Why This Matters for Engineers
When upgrading or migrating an RDS database, a missing or misconfigured parameter can cause performance degradation, application errors, or security compliance violations. The challenge is compounded by the fact that:
- Parameters valid in one engine version may not exist in another
- Some parameters behave differently across engines (e.g., RDS MySQL vs Aurora MySQL)
- Aurora cluster parameter groups have a different structure from RDS instance parameter groups
- Certain parameters require prerequisites to be set before they can be applied
(e.g.,
innodb_flush_log_at_trx_commitin Aurora MySQL 3)
Traditional Approach vs This Solution
| Traditional Manual Approach | This Solution | |
|---|---|---|
| Method | Console UI — apply one by one | AWS CLI script — fully automated |
| Time | Hours for large parameter groups | Minutes |
| Error risk | High — easy to miss parameters | Low — automated validation |
| Compatibility check | Manual — check docs per parameter | Automatic — API-driven |
| Cross-region | Not straightforward | Built-in support |
| Audit trail | None | Full migration report generated |
| Engine support | Any (manual) | MySQL and PostgreSQL engines |
This guide provides an AWS CLI + Bash script that automates the entire process — no Python or third-party tools required.
⚠️ Important: Always Review Parameters Before Applying
This script automates parameter migration as a starting point — not a final configuration.
Carrying over parameters as-is when upgrading or changing the engine type is not a best practice. Parameters may behave differently depending on the target engine version or type. Before applying migrated parameters to a production database, you must:
- Review the migration report — check APPLIED, SKIPPED, INCOMPATIBLE, and FAILED sections
- Verify each applied parameter — confirm the value is appropriate for the target engine
- Test in a non-production environment first — validate application behavior before promoting to production
- Consult engine-specific documentation — parameter semantics can differ between RDS and Aurora, or between major versions
The script provides visibility and automation, but the final review and validation is the responsibility of the engineer or DBA.
Common Use Cases
| Source Engine | Target Engine |
|---|---|
| RDS PostgreSQL | Aurora PostgreSQL |
| Aurora PostgreSQL | RDS PostgreSQL |
| Aurora MySQL | RDS MySQL |
| RDS MySQL | Aurora MySQL |
| RDS MariaDB | Aurora MySQL |
| Any RDS Engine Same engine | Any RDS Engine Same engine (version upgrade) |
| Any RDS Engine Same engine | Any RDS Engine Same engine (cross-region copy) |
Note: The script relies on the AWS API
IsModifiableflag to determine what can be applied. Parameters not found in the target engine are reported as INCOMPATIBLE. Parameters found but not modifiable are reported as SKIPPED. Parameters rejected by the API due to constraints are reported as FAILED.
How It Works
Source Parameter Group Target Parameter Group
(user-modified params only) (new version / new engine)
│ │
│ export_params() │ create_target_group()
▼ ▼
source_params.json ──────► target_valid_params.json
│ filter │
│ _params() │
▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────────┐
│ APPLICABLE │ │ SKIPPED │ │ INCOMPATIBLE │
│ │ │ │ │ │
│ Found in │ │ Found in │ │ Not found in │
│ target AND │ │ target BUT │ │ target engine │
│ modifiable │ │ not │ │ at all │
└──────┬──────┘ │ modifiable │ └──────────────────┘
│ └─────────────┘
▼
apply_params() ── batch apply
│
├── ✅ Success → APPLIED
│
└── ❌ Batch fail → retry individually
│
├── ✅ Success → APPLIED
├── 🔄 Has prerequisite → apply prereq → retry → APPLIED
└── ❌ Still fail → FAILED (with reason)
Prerequisites
# Install AWS CLI curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip && sudo ./aws/install # Install jq # Amazon Linux / RHEL sudo yum install -y jq # Ubuntu / Debian sudo apt-get install -y jq # macOS brew install jq # Configure AWS credentials aws configure # Verify aws --version && jq --version
Script
📥 Download: migrate_param_group.sh
# Download directly with curl curl -O https://raw.githubusercontent.com/awslabs/rds-support-tools/main/rds-general/shell/migrate_param_group.sh
Run
chmod +x migrate_param_group.sh # Same region — version upgrade ./migrate_param_group.sh \ -s my-rds-pg15 \ -t my-aurora-pg15-cluster \ -f aurora-postgresql15 # Same region — engine migration ./migrate_param_group.sh \ -s my-rds-mysql80 \ -t my-aurora-mysql80-cluster \ -f aurora-mysql8.0 # Cross-region copy — same engine and version ./migrate_param_group.sh \ -s my-rds-pg15 \ -t my-rds-pg15-copy \ -f postgres15 \ -S us-east-1 \ -T ap-southeast-1 # Cross-region copy — with engine migration ./migrate_param_group.sh \ -s my-rds-pg15 \ -t my-aurora-pg15-cluster \ -f aurora-postgresql15 \ -S us-east-1 \ -T ap-southeast-1 # Dry run ./migrate_param_group.sh \ -s my-rds-pg15 \ -t my-aurora-pg15-cluster \ -f aurora-postgresql15 \ -n
Output Files
migration_migration_20260331_084920/
├── source_params.json # Exported source parameters
├── target_valid_params.json # Valid parameters in target engine
├── params_applicable.json # Parameters to be applied
├── params_skipped.json # Not modifiable in target engine
├── params_incompatible.json # Not found in target engine
└── migration_report.txt # Full migration report
Sample Report
Same Region Migration
============================================================
PARAMETER GROUP MIGRATION REPORT
Date : Tue Mar 31 08:49:29 UTC 2026
DryRun : false
============================================================
Source : ams303 [aurora-mysql8.0 | cluster | us-west-2]
Target : mysql84 [mysql8.4 | instance | us-west-2]
------------------------------------------------------------
Total Exported : 10
Applied : 6
Skipped : 0
Incompatible : 4
Failed : 0
============================================================
...
Cross-Region Copy
============================================================
PARAMETER GROUP MIGRATION REPORT
Date : Tue Mar 31 08:46:28 UTC 2026
DryRun : false
============================================================
Source : apg16 [aurora-postgresql16 | instance | us-west-2]
Target : pg17 [postgres17 | instance | us-east-1]
------------------------------------------------------------
Total Exported : 1
Applied : 1
Skipped : 0
Incompatible : 0
Failed : 0
============================================================
...
Target Group Already Exists (script stops)
=== Step 3: Create Target Parameter Group ===
[ERROR] Failed to create parameter group: mysql84
[ERROR] Reason: An error occurred (DBParameterGroupAlreadyExists) when calling the CreateDBParameterGroup operation: Parameter group mysql84 already exists
Additional Resources
- Topics
- Database
- Language
- English
Relevant content
- Accepted Answerasked 4 years ago
