Terraform aws_db_parameter_group for AWS RDS: Complete Configuration Guide

Terraform’s aws_db_parameter_group resource gives infrastructure engineers direct control over engine-level tuning for Amazon RDS without leaving HCL. Parameter groups decouple database configuration from instance provisioning, allowing reusable sets of name-value pairs that can be attached to one or more DB instances. The resource maps closely to the AWS RDS DB parameter group API, with support for family selection, per-parameter apply methods, and lifecycle behaviors that matter during major version upgrades.

How Parameter Groups Fit Into an RDS Deployment

A typical RDS deployment combines a subnet group, security group, parameter group, and the DB instance itself. The subnet group resource is an optional parameter in the aws_db_instance block. Without it, Terraform creates RDS instances in the default VPC.

hcl resource "aws_db_subnet_group" "education" { name = "education" subnet_ids = module.vpc.public_subnets tags = { Name = "Education" } }

The instance block references the subnet group, security group, and parameter group by name:

hcl resource "aws_db_instance" "education" { identifier = "education" instance_class = "db.t3.micro" allocated_storage = 5 engine = "postgres" engine_version = "18.3" username = "edu" password = var.db_password db_subnet_group_name = aws_db_subnet_group.education.name vpc_security_group_ids = [aws_security_group.rds.id] parameter_group_name = aws_db_parameter_group.education.name publicly_accessible = true skip_final_snapshot = true }

Note the following arguments. username and password are the credentials for the root user. publicly_accessible is set to true for this tutorial’s configuration. Attaching a custom parameter group lets you override engine defaults for character sets, memory allocation, logging, and durability settings while keeping the instance definition clean.

Resource Definition and Core Arguments

The aws_db_parameter_group resource provides an RDS DB parameter group resource. Documentation of available parameters for various RDS engines can be found at Aurora MySQL Parameters, Aurora PostgreSQL Parameters, MariaDB Parameters, Oracle Parameters, PostgreSQL Parameters.

A minimal definition requires a name and a family:

hcl resource "aws_db_parameter_group" "default" { name = "rds-pg" family = "mysql5.6" parameter { name = "character_set_server" value = "utf8" } parameter { name = "character_set_client" value = "utf8" } }

Argument reference for the resource includes:

Argument Required Description
name Required The name of the DB parameter group. Optional Forces new resource.
family Required The family of the DB parameter group. Must match engine and major version.
description Optional The description of the DB parameter group. Defaults to “Managed by Terraform”.
parameter Optional A list of DB parameters to apply.
tags Optional A mapping of tags to assign to the resource.
region Optional Region where this resource will be managed. Defaults to the Region set in the provider configuration.

Parameter blocks support:

Argument Required Description
name Required The name of the DB parameter.
value Required The value of the DB parameter.
apply_method Optional “immediate” (default), or “pending-reboot”. Some engines can’t apply some parameters without a reboot, and you will need to specify “pending-reboot” here.

Attributes exported by the resource are:

Attribute Description
id The db parameter group name.
arn The ARN of the db parameter group.

Import is supported using the name:

bash $ terraform import aws_db_parameter_group.rds_pg rds-pg

Families and Engine Mapping

The family must match your engine and major version. Common families include:

  • mysql8.0 for MySQL 8.0.x
  • postgres16 for PostgreSQL 16.x
  • mariadb10.11 for MariaDB 10.11.x
  • aurora-mysql8.0 for Aurora MySQL 8.0
  • aurora-postgresql16 for Aurora PostgreSQL 16

Choosing the correct family is critical. A mismatch prevents the parameter group from being attached and will cause perpetual diffs. Terraform plan showing parameter changes after an apply, i.e., perpetual diffs, can occur when the family or parameter set drifts from AWS defaults.

Apply Methods: Dynamic vs Static Parameters

Dynamic parameters take effect immediately when changed. Static parameters require a reboot of the instance before they take effect. This distinction matters a lot in Terraform.

Example for PostgreSQL 16 with mixed apply methods:

hcl resource "aws_db_parameter_group" "postgres" { name = "myapp-postgres16" family = "postgres16" description = "Custom PostgreSQL 16 parameters for myapp" parameter { name = "max_connections" value = "200" apply_method = "pending-reboot" } parameter { name = "shared_buffers" value = "{DBInstanceClassMemory/4}" apply_method = "pending-reboot" } parameter { name = "log_min_duration_statement" value = "1000" } tags = { Name = "myapp-postgres16" Environment = "production" } }

Formula values such as {DBInstanceClassMemory/4} are evaluated by RDS at instance creation, allowing memory-proportional tuning without hardcoding instance class specifics.

For MySQL 8.0 a production-ready tuning set demonstrates character set, InnoDB, and query tuning:

hcl resource "aws_db_parameter_group" "mysql" { name_prefix = "myapp-mysql80-" family = "mysql8.0" description = "Tuned MySQL 8.0 parameters" parameter { name = "character_set_server" value = "utf8mb4" } parameter { name = "collation_server" value = "utf8mb4_0900_ai_ci" } parameter { name = "innodb_buffer_pool_size" value = "{DBInstanceClassMemory*3/4}" } parameter { name = "innodb_buffer_pool_instances" value = "8" apply_method = "pending-reboot" } parameter { name = "innodb_redo_log_capacity" value = "2147483648" } parameter { name = "innodb_flush_log_at_trx_commit" value = "1" } parameter { name = "innodb_io_capacity" value = "3000" } parameter { name = "join_buffer_size" value = "262144" } parameter { name = "sort_buffer_size" value = "524288" } parameter { name = "slow_query_log" value = "1" } }

name_prefix causes Terraform to create a new parameter group with a unique suffix, update the instance if its parameter_group_name references the parameter group resource, and then delete the old one after it is no longer attached. This is useful for immutable naming strategies.

Perpetual Diff Avoidance and Default Management

If you encounter a Terraform plan showing parameter changes after an apply, see the Problematic Plan Changes example guidance. The most common cause is Terraform managing a parameter that AWS manages by default.

One approach is to omit the parameter entirely. This ensures Terraform does not attempt to modify the parameter, leaving it with AWS's default settings.

hcl resource "aws_db_parameter_group" "test" { name = "random-test-parameter" family = "mysql5.7" }

Another approach is to explicitly set the value and apply_method to match AWS defaults. Since the AWS default value is 0, selecting any other valid value e.g., 1 will resolve the issue.

hcl resource "aws_db_parameter_group" "test" { name = "random-test-parameter" family = "mysql5.7" parameter { name = "default_password_lifetime" value = "1" } }

When the AWS default value is 0 and the parameter uses pending-reboot by default, you must align both value and apply_method to avoid conflicts.

hcl resource "aws_db_parameter_group" "test" { name = "random-test-parameter" family = "mysql5.7" parameter { apply_method = "pending-reboot" name = "default_password_lifetime" value = "0" } }

Explicitly set the apply_method to match AWS's default value for this parameter pending-reboot. This prevents conflicts between Terraform's default immediate and AWS's default where the value is not changing.

Lifecycle and Recreation Behavior

The create_before_destroy lifecycle configuration is necessary for modifications that force re-creation of an existing, in-use parameter group. This includes common situations like changing the group name or bumping the family version during a major version upgrade. This configuration will prevent destruction of the deposed parameter group while still in use by the database during upgrade.

Note: Using create_before_destroy requires that the new parameter group is created with a different name than the existing one.

hcl resource "aws_db_parameter_group" "default" { name = "rds-pg" family = "mysql5.6" lifecycle { create_before_destroy = true } }

This pattern is essential when upgrading families, for example from mysql5.6 to mysql5.7, because RDS requires a new parameter group and a reboot window.

Hands-On Workflow and Verification

After applying a parameter group change, Terraform shows a plan summary and then applies:

bash $ terraform apply aws_db_parameter_group.education: Refreshing state... [id=education] module.vpc.aws_vpc.this[0]: Refreshing state... [id=vpc-03d07a04a25ae3f80] Plan: 1 to add, 1 to change, 0 to destroy.

Once complete, outputs can be used to connect and verify:

Outputs: rds_hostname = <sensitive> rds_port = <sensitive> rds_replica_connection_parameters = "-h education-replica.cyfmek5yt2i5.us-east-2.rds.amazonaws.com -p 5432 -U edu postgres" rds_username = <sensitive>

As with the original instance, it may take 5-7 minutes to provision the replica, and a few additional minutes to make updates to the primary instance. Once it is complete, use the new endpoint to connect to the replica database instance to verify your configuration.

Common Pitfalls

  • Using a family that does not match the engine version leads to API validation errors.
  • Setting apply_method = "immediate" on a static parameter causes Terraform to wait indefinitely for an effective change that requires reboot.
  • Forgetting to attach the parameter group via parameter_group_name on aws_db_instance results in the group existing but unused.
  • Changing the name of an in-use parameter group without create_before_destroy causes downtime.

Conclusion

The aws_db_parameter_group resource is the mechanism for codifying engine tuning, compliance, and observability settings for RDS. Success depends on precise family selection, correct applymethod for dynamic versus static parameters, and lifecycle handling for upgrades. By pairing parameter groups with subnet groups, security groups, and instance definitions, Terraform can reproduce RDS environments consistently across development, staging, and production. The key operational practices are to avoid managing parameters that AWS defaults manage, to explicitly set applymethod where AWS defaults differ from Terraform defaults, and to use create_before_destroy when changing group identity or family during major version upgrades. These patterns eliminate perpetual diffs, prevent accidental reboots, and keep infrastructure as code aligned with RDS behavior.

Sources

  1. HashiCorp Terraform AWS RDS Tutorial
  2. HashiCorp Terraform Provider AWS DB Parameter Group
  3. Koding Terraform AWS DB Parameter Group Docs
  4. OneUptime Configure RDS Parameter Groups in Terraform

Related Posts