Terraform Managed Pub/Sub Topics and Subscriptions for Google Cloud

Google Cloud Pub/Sub is one of those services that shows up in almost every GCP architecture. Whether you are building event-driven microservices, streaming data into BigQuery, or triggering Cloud Functions, Pub/Sub is usually the glue in between. And if you are managing your infrastructure with Terraform, you will want to define your topics and subscriptions as code rather than clicking through the Console.

This guide walks through creating Pub/Sub topics and subscriptions with Terraform, covering the common configurations you will need in a real project. It combines practical provider setup, module patterns, dead-letter handling, IAM wiring, and integration points with other GCP services.

Provider and Project Prerequisites

Before creating any Pub/Sub resources, make sure your Terraform configuration includes the Google provider.

The minimum provider configuration is:

```hcl
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}

provider "google" {
project = var.project_id
region = var.region
}
```

A commonly used project structure for a Pub/Sub codebase is:

.
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── modules/
└── pubsub/
├── main.tf
├── variables.tf
├── topics.tf
└── outputs.tf

Prerequisites for working with Terraform and Pub/Sub:

  • Google Cloud SDK installed and configured
  • Terraform installed version 1.0.0 or later
  • A GCP project with billing enabled

Variable definitions typically used:

```hcl
variable "project_id" {
description = "The GCP project ID"
type = string
}

variable "region" {
description = "The GCP region"
type = string
default = "us-central1"
}

variable "topic_name" {
description = "Name of the Pub/Sub topic"
type = string
}

variable "subscription_name" {
description = "Name of the Pub/Sub subscription"
type = string
}
```

Before you begin with Cloud Functions integration:

  • Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

Roles required to select or create a project:

  • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
  • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission

Costs to be aware of when deploying Pub/Sub functions:

In this document, you use the following billable components of Google Cloud:

For details, see Cloud Run functions pricing.

Creating a Basic Topic and Pull Subscription

The simplest Pub/Sub setup is a topic with a pull subscription.

A basic topic resource can include labels and retention:

hcl resource "google_pubsub_topic" "topic" { name = var.topic_name labels = { environment = "production" } message_retention_duration = "86600s" }

message_retention_duration is expressed in seconds. A value of 86600s represents 24 hours.

A basic subscription can be defined alongside the topic:

hcl resource "google_pubsub_subscription" "subscription" { name = var.subscription_name topic = google_pubsub_topic.topic.name }

When you run Terraform, the topic and subscription are created in the same project and region as defined by the provider. Adjust your Terraform code until the plan shows no changes.

Topic Configuration Patterns

Topic configuration with schema settings and retention is common in production:

hcl resource "google_pubsub_topic" "topic" { name = var.topic_name labels = { environment = "production" } message_retention_duration = "86600s" schema_settings { schema = } }

The message retention duration can be increased for longer replay windows. In reusable modules the default is often 604800s, which is 7 days.

Dead Letter Queue and IAM Wiring

Resilience patterns require a dead-letter topic and explicit IAM grants for the Pub/Sub service account.

Service account for Pub/Sub:

hcl data "google_project" "current" {}

The Pub/Sub service account can be referenced as:

serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com

Grant Pub/Sub service account permission to publish to the DLQ topic:

hcl resource "google_pubsub_topic_iam_member" "dlq_publisher" { topic = google_pubsub_topic.order_events_dlq.name role = "roles/pubsub.publisher" member = "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com" }

Grant Pub/Sub service account permission to subscribe on the source subscription:

hcl resource "google_pubsub_subscription_iam_member" "dlq_subscriber" { subscription = google_pubsub_subscription.order_processor_with_dlq.name role = "roles/pubsub.subscriber" member = "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com" }

A reusable module for a topic with DLQ can be structured as:

```hcl
variable "topic_name" {
type = string
}

variable "subscriptions" {
type = map(object({
ackdeadline = number
max
delivery_attempts = number
}))
}

variable "labels" {
type = map(string)
default = {}
}

data "google_project" "current" {}

locals {
pubsubserviceaccount = "serviceAccount:service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
}

resource "googlepubsubtopic" "main" {
name = var.topicname
labels = var.labels
message
retention_duration = "604800s"
}

resource "googlepubsubtopic" "dlq"
```

If you have many topics and subscriptions that follow similar patterns, wrap them in a Terraform module:

```hcl

modules/pubsub-topic/main.tf - Reusable module for topic with DLQ

```

Module Usage and Versioning

This module makes it easy to create Google Cloud Pub/Sub topic and subscriptions associated with the topic.

This module is meant for use with Terraform 0.13+ and tested using Terraform 1.0+. If you find incompatibilities using Terraform >=0.13, please open an issue. If you haven't upgraded and need a Terraform 0.12.x-compatible version of this module, the last released version intended for Terraform 0.12.x is v1.9.0.

This is a simple usage of the module.

Terraform can handle this.

Integration with Other GCP Components

The configuration parameters are based on the terraform-google-pubsub Terraform module.

Component connections update both the application and the generated Terraform code.

Connected component Application updates Background information
Compute Engine instance template The Compute Engine instances can publish to and receive messages from the Pub/Sub topic. The Pub/Sub topic ID is added to the Compute Engine instance template metadata.
Instance templates
Service account The service account can manage Pub/Sub topics, and pull messages from subscriptions. The roles/pubsub.editor role is added to the service account.
The service account name and email information is added to the Pub/Sub pull subscription.
Access control with IAM
BigQuery The Pub/Sub subscription can write messages to the BigQuery dataset. The BigQuery dataset information is added to the BigQuery subscription fields.
BigQuery subscriptions
Cloud Run The Cloud Run service can receive messages or publish to the Pub/Sub topic. The Pub/Sub topic ID is added to the Cloud Run environment variables.
The roles/pubsub.publisher and roles/pubsub.subscriber roles are added to the Cloud Run service account.
The Cloud Run service is added to the Pub/Sub push and pull subscription fields. Use Pub/Sub with Cloud Run tutorial
Cloud Storage The Pub/Sub subscription can write messages to the Cloud Storage

Service account integration details:

  • The service account can manage Pub/Sub topics, and pull messages from subscriptions.
  • The roles/pubsub.editor role is added to the service account.
  • The service account name and email information is added to the Pub/Sub pull subscription.

BigQuery integration details:

  • The Pub/Sub subscription can write messages to the BigQuery dataset.
  • The BigQuery dataset information is added to the BigQuery subscription fields.

Cloud Run integration details:

  • The Cloud Run service can receive messages or publish to the Pub/Sub topic.
  • The Pub/Sub topic ID is added to the Cloud Run environment variables.
  • The roles/pubsub.publisher and roles/pubsub.subscriber roles are added to the Cloud Run service account.
  • The Cloud Run service is added to the Pub/Sub push and pull subscription fields.

Common Pitfalls

A few things that trip people up when managing Pub/Sub with Terraform:

  • Subscription expiration: By default, subscriptions expire after 31 days of inactivity. If your subscription seems to disappear, set expiration_policy { ttl = "" } to disable expiration.
  • Changing topic on a subscription: You cannot change the topic of an existing subscription. Terraform will destroy and recreate it, which means you lose any unprocessed messages.
  • IAM propagation delays: After granting IAM roles, it can take a few minutes for the permissions to propagate. If dead letter publishing fails immediately after creation, wait and retry.
  • Message ordering: If you need ordered delivery, you must set enablemessageordering = true on the subscription. This cannot be changed after creation without recreating the subscription.

Provider version differences are also common. One configuration uses:

hcl required_providers { google = { source = "hashicorp/google" version = "~> 4.0" } }

Another uses ~> 5.0. Match the version to the provider features you need.

Conclusion

Terraform is the right way to manage Pub/Sub infrastructure in any serious GCP project. It gives you version control, peer review, and reproducibility for your messaging infrastructure. Start with simple topics and pull subscriptions, add dead letter topics for resilience, and use modules when patterns start repeating. The initial investment in writing Terraform code pays for itself the first time you need to replicate your setup in a new environment.

A solid baseline includes provider configuration with project and region variables, explicit topic resources with labels and message retention, subscriptions with appropriate ack deadlines and dead-letter settings, IAM members for the Pub/Sub service account, and modules for reuse across environments. Pair that with awareness of subscription expiration, immutable topic binding, IAM propagation delays, and message ordering constraints, and you have a production-ready Pub/Sub foundation that can be versioned, reviewed, and reproduced.

Sources

  1. OneUptime Blog
  2. The Cloud Panda
  3. Google Cloud Docs Functions Terraform Pub/Sub
  4. Google Cloud Application Design Center
  5. Terraform Google Modules GitHub

Related Posts