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({
ackdeadline = number
maxdeliveryattempts = number
}))
}
variable "labels" {
type = map(string)
default = {}
}
data "googleproject" "current" {}
locals {
pubsubserviceaccount = "serviceAccount:service-${data.googleproject.current.number}@gcp-sa-pubsub.iam.gserviceaccount.com"
}
resource "googlepubsubtopic" "main" {
name = var.topicname
labels = var.labels
messageretentionduration = "604800s"
}
resource "googlepubsub_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.,
604800sfor 7 days. - Model multi-topic configurations with a
pubsub_configmap variable and flatten locals for subscriptions. - Grant IAM via
google_pubsub_topic_iam_memberandgoogle_pubsub_subscription_iam_memberusing the project-scoped service account. - Wrap DLQ and ordering patterns in reusable modules with inputs for
topic_name,subscriptions, andlabels. - 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
- github.com/terraform-google-modules/terraform-google-pubsub
- blog.amyinfo.com/2025-03-15-terraform-pubsub-module/
- oneuptime.com/blog/post/2026-02-17-how-to-create-pubsub-topics-and-subscriptions-with-terraform/view
- docs.cloud.google.com/functions/docs/tutorials/terraform-pubsub
- www.linkedin.com/pulse/integrating-google-cloud-pubsub-terraform-spring-boot-xiloj-herrera-witme