Skip to main content
The Aiven Provider for Terraform enables you to define, provision, and manage your Aiven infrastructure using infrastructure-as-code principles.

Why use Terraform

Infrastructure as Code

Define your infrastructure in version-controlled configuration files

Reproducible environments

Create identical environments across dev, staging, and production

Plan before apply

Preview changes before applying them to your infrastructure

State management

Track resource state and dependencies automatically

Prerequisites

Quick start

1

Create a token

Generate an authentication token from the Aiven Console under User Profile > Tokens
2

Configure the provider

Create a main.tf file with the provider configuration:
main.tf
terraform {
  required_providers {
    aiven = {
      source  = "aiven/aiven"
      version = "~> 4.0"
    }
  }
}

provider "aiven" {
  api_token = var.aiven_api_token
}
3

Create variables file

Create a variables.tf file:
variables.tf
variable "aiven_api_token" {
  description = "Aiven API token"
  type        = string
  sensitive   = true
}
4

Set your token

Create a terraform.tfvars file (don’t commit this!):
terraform.tfvars
aiven_api_token = "YOUR_TOKEN_HERE"
Or set it as an environment variable:
export TF_VAR_aiven_api_token="YOUR_TOKEN_HERE"
5

Initialize Terraform

terraform init

Basic examples

Create a PostgreSQL service

resource "aiven_pg" "postgres" {
  project                 = "my-project"
  service_name            = "my-postgres"
  cloud_name              = "google-europe-north1"
  plan                    = "startup-4"
  maintenance_window_dow  = "sunday"
  maintenance_window_time = "10:00:00"

  pg_user_config {
    pg_version = "16"
    
    public_access {
      pg = true
    }
  }
}

# Output the connection URI
output "postgres_uri" {
  value     = aiven_pg.postgres.service_uri
  sensitive = true
}

Create an Apache Kafka service

resource "aiven_kafka" "kafka" {
  project      = "my-project"
  service_name = "my-kafka"
  cloud_name   = "google-europe-north1"
  plan         = "business-4"

  kafka_user_config {
    kafka_version = "3.6"
    
    kafka {
      auto_create_topics_enable = true
    }
    
    kafka_connect = true
  }
}

# Create a Kafka topic
resource "aiven_kafka_topic" "orders" {
  project      = aiven_kafka.kafka.project
  service_name = aiven_kafka.kafka.service_name
  topic_name   = "orders"
  partitions   = 3
  replication  = 2
  
  config {
    retention_ms = 604800000 # 7 days
  }
}

# Create a Kafka user
resource "aiven_kafka_user" "app_user" {
  project      = aiven_kafka.kafka.project
  service_name = aiven_kafka.kafka.service_name
  username     = "app-user"
}

# Create ACL for the user
resource "aiven_kafka_acl" "app_user_read" {
  project      = aiven_kafka.kafka.project
  service_name = aiven_kafka.kafka.service_name
  username     = aiven_kafka_user.app_user.username
  permission   = "read"
  topic        = aiven_kafka_topic.orders.topic_name
}

Create a database and user in PostgreSQL

resource "aiven_pg_database" "app_db" {
  project       = aiven_pg.postgres.project
  service_name  = aiven_pg.postgres.service_name
  database_name = "appdb"
}

resource "aiven_pg_user" "app_user" {
  project      = aiven_pg.postgres.project
  service_name = aiven_pg.postgres.service_name
  username     = "app_user"
}

Organization setup example

Create an organization with organizational units and projects:
# Create organization
resource "aiven_organization" "main" {
  name = "my-company"
}

# Create organizational units
resource "aiven_organizational_unit" "engineering" {
  name          = "Engineering"
  parent_id     = aiven_organization.main.id
}

resource "aiven_organizational_unit" "production" {
  name          = "Production"
  parent_id     = aiven_organizational_unit.engineering.id
}

resource "aiven_organizational_unit" "development" {
  name          = "Development"
  parent_id     = aiven_organizational_unit.engineering.id
}

# Create projects
resource "aiven_project" "prod" {
  project       = "production-services"
  parent_id     = aiven_organizational_unit.production.id
}

resource "aiven_project" "dev" {
  project       = "development-services"
  parent_id     = aiven_organizational_unit.development.id
}

Advanced features

Service integrations

Integrate services together:
# PostgreSQL service
resource "aiven_pg" "postgres" {
  project      = "my-project"
  service_name = "my-postgres"
  cloud_name   = "google-europe-north1"
  plan         = "startup-4"
}

# InfluxDB service for metrics
resource "aiven_influxdb" "metrics" {
  project      = "my-project"
  service_name = "metrics-db"
  cloud_name   = "google-europe-north1"
  plan         = "startup-4"
}

# Integrate PostgreSQL metrics to InfluxDB
resource "aiven_service_integration" "pg_to_influx" {
  project                  = "my-project"
  integration_type         = "metrics"
  source_service_name      = aiven_pg.postgres.service_name
  destination_service_name = aiven_influxdb.metrics.service_name
}

VPC and peering

# Create a VPC
resource "aiven_project_vpc" "vpc" {
  project      = "my-project"
  cloud_name   = "google-europe-north1"
  network_cidr = "10.0.0.0/24"
}

# Create service in VPC
resource "aiven_pg" "postgres" {
  project      = "my-project"
  service_name = "my-postgres"
  cloud_name   = "google-europe-north1"
  plan         = "startup-4"
  
  project_vpc_id = aiven_project_vpc.vpc.id
}

# Create VPC peering connection (AWS example)
resource "aiven_aws_vpc_peering_connection" "peering" {
  vpc_id              = aiven_project_vpc.vpc.id
  aws_account_id      = "123456789012"
  aws_vpc_id          = "vpc-1234567890abcdef0"
  aws_vpc_region      = "us-east-1"
}

Static IP addresses

resource "aiven_static_ip" "ip" {
  project    = "my-project"
  cloud_name = "google-europe-north1"
}

resource "aiven_pg" "postgres" {
  project      = "my-project"
  service_name = "my-postgres"
  cloud_name   = "google-europe-north1"
  plan         = "startup-4"
  
  static_ips = [aiven_static_ip.ip.static_ip_address_id]
}

Connection pooling (PostgreSQL)

resource "aiven_connection_pool" "pool" {
  project       = aiven_pg.postgres.project
  service_name  = aiven_pg.postgres.service_name
  database_name = aiven_pg_database.app_db.database_name
  pool_name     = "app_pool"
  pool_size     = 25
  pool_mode     = "transaction"
  username      = aiven_pg_user.app_user.username
}

output "pool_uri" {
  value     = aiven_connection_pool.pool.connection_uri
  sensitive = true
}

Workflow commands

Initialize

Download provider and initialize working directory:
terraform init

Plan

Preview changes before applying:
terraform plan
Save plan to a file:
terraform plan -out=tfplan

Apply

Apply changes to create/update infrastructure:
terraform apply
Apply without confirmation:
terraform apply -auto-approve
Apply a saved plan:
terraform apply tfplan

Destroy

Destroy all managed infrastructure:
This will permanently delete all resources defined in your Terraform configuration.
terraform destroy

Import

Import existing Aiven resources:
terraform import aiven_pg.postgres my-project/my-postgres

State management

# List resources in state
terraform state list

# Show resource details
terraform state show aiven_pg.postgres

# Remove resource from state (doesn't delete actual resource)
terraform state rm aiven_pg.postgres

Best practices

Store Terraform state remotely for team collaboration:
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "aiven/terraform.tfstate"
    region = "us-east-1"
  }
}
Create reusable modules for common patterns:
module "postgres" {
  source = "./modules/postgres"
  
  project    = "my-project"
  name       = "my-postgres"
  cloud      = "google-europe-north1"
  plan       = "startup-4"
  pg_version = "16"
}
Manage multiple environments:
terraform workspace new production
terraform workspace new staging
terraform workspace select production
Reference in configuration:
resource "aiven_pg" "postgres" {
  service_name = "postgres-${terraform.workspace}"
  # ...
}
Prevent accidental deletion:
resource "aiven_pg" "postgres" {
  # ...
  
  lifecycle {
    prevent_destroy = true
  }
}
Reference existing resources:
data "aiven_project" "existing" {
  project = "my-project"
}

resource "aiven_pg" "postgres" {
  project = data.aiven_project.existing.project
  # ...
}

Available resources

The Aiven Terraform Provider supports a wide range of resources:

Services

  • PostgreSQL: aiven_pg
  • MySQL: aiven_mysql
  • Apache Kafka: aiven_kafka
  • Apache Kafka Connect: aiven_kafka_connect
  • Apache Flink: aiven_flink
  • OpenSearch: aiven_opensearch
  • Redis: aiven_redis
  • InfluxDB: aiven_influxdb
  • Grafana: aiven_grafana
  • And more…

Service components

  • Databases: aiven_pg_database, aiven_mysql_database
  • Users: aiven_pg_user, aiven_kafka_user
  • Topics: aiven_kafka_topic
  • ACLs: aiven_kafka_acl
  • Connectors: aiven_kafka_connector
  • Connection pools: aiven_connection_pool

Platform resources

  • Projects: aiven_project
  • Organizations: aiven_organization
  • Organizational units: aiven_organizational_unit
  • VPCs: aiven_project_vpc
  • VPC peering: aiven_aws_vpc_peering_connection
  • Static IPs: aiven_static_ip

Troubleshooting

Enable debug logging

export TF_LOG=DEBUG
terraform apply

Check provider version

terraform version

Refresh state

terraform refresh

Migration from other tools

Migrate existing Aiven resources to Terraform:
1

Create resource blocks

Write Terraform configuration for existing resources
2

Import resources

terraform import aiven_pg.postgres my-project/my-postgres
3

Verify state

terraform plan
Should show no changes needed

Build docs developers (and LLMs) love