Skip to main content
This example provisions a production-ready Oracle Enterprise Edition 19c RDS instance with bring-your-own-license (BYOL) licensing, character set configuration, and cross-region automated backup replication using a KMS key.

Configuration

main.tf
provider "aws" {
  region = local.region
}

provider "aws" {
  alias  = "region2"
  region = local.region2
}

data "aws_caller_identity" "current" {}
data "aws_availability_zones" "available" {}

locals {
  name    = "complete-oracle"
  region  = "eu-west-1"
  region2 = "eu-central-1"

  vpc_cidr = "10.0.0.0/16"
  azs      = slice(data.aws_availability_zones.available.names, 0, 3)

  tags = {
    Name       = local.name
    Example    = local.name
    Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds"
  }
}

################################################################################
# RDS Module
################################################################################

module "db" {
  source = "terraform-aws-modules/rds/aws"

  identifier = "demodb-oracle"

  engine               = "oracle-ee"
  engine_version       = "19"
  family               = "oracle-ee-19" # DB parameter group
  major_engine_version = "19"           # DB option group
  instance_class       = "db.t3.large"
  license_model        = "bring-your-own-license"

  allocated_storage     = 20
  max_allocated_storage = 100

  # Make sure that database name is capitalized, otherwise RDS will try to recreate RDS instance every time
  # Oracle database name cannot be longer than 8 characters
  db_name  = "ORACLE"
  username = "complete_oracle"
  port     = 1521

  multi_az               = true
  db_subnet_group_name   = module.vpc.database_subnet_group
  vpc_security_group_ids = [module.security_group.security_group_id]

  maintenance_window              = "Mon:00:00-Mon:03:00"
  backup_window                   = "03:00-06:00"
  enabled_cloudwatch_logs_exports = ["alert", "audit"]
  create_cloudwatch_log_group     = true

  backup_retention_period = 1
  skip_final_snapshot     = true
  deletion_protection     = false

  performance_insights_enabled          = true
  performance_insights_retention_period = 7
  create_monitoring_role                = true

  # See here for support character sets https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.OracleCharacterSets.html
  character_set_name       = "AL32UTF8"
  nchar_character_set_name = "AL16UTF16"

  tags = local.tags
}

module "db_disabled" {
  source = "terraform-aws-modules/rds/aws"

  identifier = "${local.name}-disabled"

  create_db_instance        = false
  create_db_parameter_group = false
  create_db_option_group    = false
}

################################################################################
# RDS Automated Backups Replication Module
################################################################################

module "kms" {
  source      = "terraform-aws-modules/kms/aws"
  version     = "~> 1.0"
  description = "KMS key for cross region automated backups replication"

  # Aliases
  aliases                 = [local.name]
  aliases_use_name_prefix = true

  key_owners = [data.aws_caller_identity.current.arn]

  tags = local.tags

  providers = {
    aws = aws.region2
  }
}

module "db_automated_backups_replication" {
  source = "terraform-aws-modules/rds/aws//modules/db_instance_automated_backups_replication"

  source_db_instance_arn = module.db.db_instance_arn
  kms_key_arn            = module.kms.key_arn

  providers = {
    aws = aws.region2
  }
}

################################################################################
# Supporting Resources
################################################################################

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 6.0"

  name = local.name
  cidr = local.vpc_cidr

  azs              = local.azs
  public_subnets   = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
  private_subnets  = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
  database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]

  create_database_subnet_group = true

  tags = local.tags
}

module "security_group" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "~> 5.0"

  name        = local.name
  description = "Complete Oracle example security group"
  vpc_id      = module.vpc.vpc_id

  # ingress
  ingress_with_cidr_blocks = [
    {
      from_port   = 1521
      to_port     = 1521
      protocol    = "tcp"
      description = "Oracle access from within VPC"
      cidr_blocks = module.vpc.vpc_cidr_block
    },
  ]

  tags = local.tags
}

Oracle-specific configuration

Engine identifiers

RDS Oracle supports two engine identifiers:
EngineEditionLicense model
oracle-eeEnterprise Editionbring-your-own-license only
oracle-se2Standard Edition 2bring-your-own-license or license-included
The family value follows the format "oracle-ee-19" or "oracle-se2-19", and major_engine_version is the version number string "19".

License model

Oracle requires an explicit license_model:
  • "bring-your-own-license" — you supply existing Oracle licenses. Required for Enterprise Edition.
  • "license-included" — the Oracle license is included in the instance price. Only available for Standard Edition 2.

Database name constraints

The Oracle db_name (SID) must be capitalized and 8 characters or fewer. If you specify a lowercase name, Terraform will detect drift after creation because RDS stores it in uppercase, causing repeated plan/apply cycles. Use "ORACLE" not "oracle".

Character sets (immutable)

Both character_set_name and nchar_character_set_name are immutable after creation. Changing either value requires destroying and recreating the RDS instance. Choose carefully before first apply.
The example uses:
VariableValueDescription
character_set_name"AL32UTF8"Database character set. AL32UTF8 is the Oracle implementation of the Unicode UTF-8 encoding — the recommended choice for new databases.
nchar_character_set_name"AL16UTF16"National character set used for NCHAR, NVARCHAR2, and NCLOB columns. AL16UTF16 is the default and recommended value.
For a full list of supported character sets, see the Oracle Character Sets documentation.

CloudWatch log exports

Oracle supports the following log export types:
Log typeDescription
alertOracle alert log (instance errors and events)
auditUnified auditing trail
listenerOracle listener log
traceOracle trace files

Outputs

OutputDescription
db_instance_addressDNS hostname of the RDS instance
db_instance_endpointFull connection endpoint including port
db_instance_identifierThe RDS instance identifier
db_instance_engine_version_actualThe resolved engine version running
db_instance_portDatabase port (1521)
db_instance_nameThe database name (SID)
db_instance_usernameMaster username (sensitive)
db_instance_master_user_secret_arnARN of the Secrets Manager secret
db_parameter_group_idThe parameter group name
db_parameter_group_arnARN of the parameter group
db_instance_cloudwatch_log_groupsMap of CloudWatch log group names and ARNs

Build docs developers (and LLMs) love