Terraform Google Modules for Pub/Sub: Provisioning Topics, Subscriptions, and IAM as Code

Google Cloud Pub/Sub is a core messaging backbone for event-driven architectures on GCP. When infrastructure is managed with Terraform, topics and subscriptions are defined declaratively rather than through console clicks. The Terraform Google modules and patterns for Pub/Sub provide reusable, tested building blocks for topics, push and pull subscriptions, dead-letter queues, BigQuery export, and IAM bindings.

This article covers the official terraform-google-modules/pubsub/google module, handcrafted module patterns for multi-topic configurations, IAM grants for service accounts, and provider setup for Pub/Sub functions. All specifics below come from the reference materials.

Module Overview and Compatibility

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

The 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.

A minimal example from the example directory shows the module invocation shape:

hcl module "pubsub" { source = "terraform-google-modules/pubsub/google" version = "~> 8.7" topic = "tf-topic" project_id = "my-pubsub-project" push_subscriptions = [ { name = "push" // required ack_deadline_seconds = 20 // optional push_endpoint = "https://example.com" // required x-goog-version = "v1beta1" // optional oidc_service_account_email = "[email protected]" // optional audience = "example" // optional expiration_policy = "1209600s" // optional dead_letter_topic = "projects/my-pubsub-project/topics/example-dl-topic" // optional max_delivery_attempts = 5 // optional maximum_backoff = "600s" // optional minimum_backoff = "300s" // optional filter = "attributes.domain = \"com\"" // optional enable_message_ordering = true // optional } ] pull_subscriptions = [ { name = "pull" // required ack_deadline_seconds = 20 // optional dead_letter_topic = "projects/my-pubsub-project/topics/example-dl-topic" // optional max_delivery_attempts = 5 // optional maximum_backoff = "600s" // optional minimum_backoff = "300s" // optional filter = "attributes.domain = \"com\"" // optional enable_message_ordering = true // optional service_account = "[email protected]" // optional enable_exactly_once_delivery = true // optional } ] bigquery_subscriptions = [ { name = "bigquery" // required table = "project.dataset.table" // required use_topic_schema = true // optional use_table_schema = false // } ]

The module accepts a topic name and project_id and arrays for pushsubscriptions, pullsubscriptions, and bigquery_subscriptions. Each subscription entry exposes required fields like name and optional fields for ack deadline, dead-letter topic, backoff, filtering, ordering, and service account.

Provider Configuration for Pub/Sub

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

hcl terraform { required_providers { google = { source = "hashicorp/google" version = "~> 5.0" } } } provider "google" { project = var.project_id region = var.region } variable "project_id" { description = "The GCP project ID" type = string } variable "region" { description = "The GCP region" type = string default = "us-central1" }

This provider block is the baseline for all Pub/Sub topic and subscription resources. The region variable defaults to us-central1 and the project is supplied via variable.

Creating a Basic Topic

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

Declarative Topic and Subscription Patterns

Create a Terraform module to create GCP pubsub resources, including topics, subscriptions and iam permissions.

Terraform code

First define a Terraform variable pubsub_config to store your Pub/Sub configuration, then extract your subscriptions to a local variable.

hcl variable "pubsub_config" { type = map(object({ subscriptions = list(object({ name = string subscribers = list(string) })) publishers = list(string) })) description = "Pub/Sub configuration, use topics name as key" } locals { subscriptions = flatten([ for topic, config in var.pubsub_config : [ for sub in config.subscriptions : { topic = topic name = sub.name subscribers = sub.subscribers } if length(config.subscriptions) > 0 ] ]) }

Create Pub/Sub Topics

hcl resource "google_pubsub_topic" "topics" { for_each = var.pubsub_config name = each.key project = var.project_id message_retention_duration = "604800s" }

Create subscriptions for every topics

hcl resource "google_pubsub_subscription" "subscriptions" { for_each = tomap({ for subscription in local.subscriptions : "${subscription.topic}-${subscription.name}-subscription" => { name = subscription.name topic = subscription.topic } }) name = each.value.name topic = google_pubsub_topic.topics[each.value.topic].name project = var.project_id ack_deadline_seconds = 600 }

Grant Topic Publisher role to GSA

hcl resource "google_pubsub_topic_iam_binding"

The pattern uses a map variable keyed by topic name. Each topic entry contains subscriptions with name and subscribers. The locals block flattens subscriptions across topics for resource creation. Topics are created with a 7-day message retention via message_retention_duration = "604800s". Subscriptions use ack_deadline_seconds = 600.

Dead-Letter Queues and Service Account Permissions

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.

Granting permissions to the Pub/Sub service account for DLQ handling is a common requirement:

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" } 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" } data "google_project" "current" {}

The service account reference uses service-${data.google_project.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com. This grants publish permission to the DLQ topic and subscribe permission on the source subscription.

Reusable Module Patterns with DLQ

Using Modules for Reusable Patterns

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

variable "topicname" {
type = string
}
variable "subscriptions" {
type = map(object({
ack
deadline = number
maxdeliveryattempts = number
}))
}
variable "labels" {
type = map(string)
default = {}
}
data "googleproject" "current" {}
locals {
pubsub
serviceaccount = "serviceAccount:service-${data.googleproject.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
}
resource "googlepubsubtopic" "main" {
name = var.topicname
labels = var.labels
message
retentionduration = "604800s"
}
resource "google
pubsub_topic" "dlq"
```

The reusable module defines inputs for topic_name, subscriptions as a map with ack_deadline and max_delivery_attempts, and optional labels. It captures the project-scoped Pub/Sub service account in a local and creates a main topic with a 7-day retention.

Pub/Sub Functions Deployment with Terraform

This tutorial demonstrates how to deploy a Pub/Sub function by uploading a function source code zip file to a Cloud Storage bucket, using Terraform to provision the resources. Terraform is an open source tool that lets you provision Google Cloud resources with declarative configuration files.

This tutorial uses a Node.js function as an example, but it also works with Python, Go, and Java functions. The instructions are the same regardless of which of these runtimes you are using. See Hashicorp's reference pages for details on using Terraform with the Cloud Functions v2 API.

Objectives

  • Learn how to use Terraform to deploy a Pub/Sub function.

Costs

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

For details, see Cloud Run functions pricing.

Before you begin

  • 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 resource manager.projects.create permission

The tutorial ties Pub/Sub topics to Cloud Functions triggers via Terraform, provisioning the function source in Cloud Storage first.

Integration with Applications

In this blog post, I'll demonstrate how to provision Google Cloud Pub/Sub resources using Terraform and integrate them with a Spring Boot 3 application running Java 21.

Application integration typically consumes the Terraform outputs for topic names and subscription names, wiring producers and consumers in Spring Boot configuration.

Comparison of Subscription Types

Feature Push Subscription Pull Subscription BigQuery Subscription
Delivery mode HTTP/HTTPS endpoint Client pulls Direct table load
Required fields name, push_endpoint name name, table
Common options ackdeadlineseconds, x-goog-version, oidcserviceaccountemail, audience, expirationpolicy, deadlettertopic, maxdeliveryattempts, maximumbackoff, minimumbackoff, filter, enablemessageordering ackdeadlineseconds, deadlettertopic, maxdeliveryattempts, maximumbackoff, minimumbackoff, filter, enablemessageordering, serviceaccount, enableexactlyoncedelivery usetopicschema, usetableschema
Typical use Cloud Functions, webhooks Microservices, workers Analytics pipeline

Best Practices Summary

  • Use the official module for standard topic + push/pull + BigQuery setups. Pin version with ~> 8.7.
  • Keep message retention explicit, e.g., 604800s for 7 days.
  • Model multi-topic configurations with a pubsub_config map variable and flatten locals for subscriptions.
  • Grant IAM via google_pubsub_topic_iam_member and google_pubsub_subscription_iam_member using the project-scoped service account.
  • Wrap DLQ and ordering patterns in reusable modules with inputs for topic_name, subscriptions, and labels.
  • Define provider with hashicorp/google ~> 5.0 and project/region variables before any Pub/Sub resources.

Conclusion

Terraform Google modules for Pub/Sub provide a mature path to codify topics, subscriptions, dead-letter queues, and IAM. The terraform-google-modules/pubsub/google module handles push, pull, and BigQuery subscriptions with fine-grained options for ack deadlines, backoff, filtering, and ordering. For organizations needing multi-topic declarative maps, a variable-driven pattern with for_each over var.pubsub_config and local flattening gives scalable creation of topics and subscriptions with consistent retention and ack settings.

Service account grants for DLQ publishing and subscribing ensure reliable retry handling. Reusable modules encapsulate topic creation, DLQ provisioning, and labeling, while provider configuration remains the foundation for all resources. Combined with Terraform-driven Cloud Functions deployment, Pub/Sub infrastructure can be versioned, reviewed, and reproduced as code across environments.

Sources

  1. github.com/terraform-google-modules/terraform-google-pubsub
  2. blog.amyinfo.com/2025-03-15-terraform-pubsub-module/
  3. oneuptime.com/blog/post/2026-02-17-how-to-create-pubsub-topics-and-subscriptions-with-terraform/view
  4. docs.cloud.google.com/functions/docs/tutorials/terraform-pubsub
  5. www.linkedin.com/pulse/integrating-google-cloud-pubsub-terraform-spring-boot-xiloj-herrera-witme

Related Posts