# Pub/Sub

> zop.dev manages Pub/Sub topics, subscriptions, and schemas, and the namespace layer mints a dedicated pubsub_editor service account per service and per cron job, keys stored as Kubernetes secrets. Subscriptions carry an expiration TTL. Google's default deletes an idle subscription after 31 days, messages and all.

Source: https://zop.dev/integrations/provision/gcp/pub-sub
Updated: 2026-08-19

---

Google Pub/Sub is the messaging backbone for event-driven services on GCP. zop.dev manages topics, subscriptions, and schemas, and wires per-workload access credentials through the namespace layer.

## Topics, subscriptions, schemas, and their IAM

Topics, subscriptions, and schemas, plus per-service and per-cronjob IAM grants with dedicated pubsub_editor service accounts whose keys land in Kubernetes secrets.

## Storage policy, ack deadline, and push config

```text
Topics: name, message_storage_policy regions, schema_settings, retention. Subscriptions: ack_deadline, retention, retain_acked, expiration TTL, push_config with endpoint and OIDC token. Schemas: name, type, definition.
```

## No Azure equivalent, MSK on AWS

Pub/Sub is GCP-only; the cross-provider messaging equivalents are MSK on AWS (and nothing yet on Azure).

## Options that map to failure modes

The subscription settings are a catalog of distributed-messaging failure modes with knobs
attached. `ack_deadline` is the redelivery clock: shorter than real processing time means
healthy work gets delivered twice, so consumers must be idempotent either way. Retention and
`retain_acked` decide whether a bad deploy can be replayed after the fact: retained acked
messages are the undo buffer for consumers that processed garbage. `push_config` with an
OIDC token moves delivery to an authenticated HTTPS endpoint, trading pull-loop control for
push simplicity. None of the defaults are wrong; all of them encode assumptions worth making
consciously.

## Idle subscriptions self-destruct

The expiration TTL is the setting that surprises people: Google's default removes a
subscription after 31 days without subscriber activity, taking its backlog with it. A consumer paused for a quarter, a disaster-recovery pipeline that only runs in
drills, a seasonal batch job: all are candidates for silent deletion followed by a confusing
absence months later. Anything intentionally idle needs its TTL extended or removed at
creation.

## Schemas bind at the beginning

A topic's schema association (`schema_settings`) is set when the topic is created. A topic
born without a schema cannot adopt one later. Teams that want enforced message contracts
need to decide at topic creation, because retrofitting means a new topic and a
producer-consumer migration.

## Credentials are per workload

The namespace layer creates a dedicated `pubsub_editor` service account per service and per
cron job, with keys landing in Kubernetes secrets. Messaging access is therefore scoped to
the workload (one consumer's credential is not the namespace's) at the cost of static keys
that belong in the rotation inventory. Pub/Sub itself bills by data volume delivered, with
retained backlog as the storage-shaped extra.
