Nov 10, 20266 min read

Cloud Tasks vs Pub/Sub on Google Cloud

When to use Cloud Tasks for explicit, rate-limited calls to one endpoint and when to use Pub/Sub for events with several consumers, with the limits that decide it, and how Encore provisions Pub/Sub on GCP from code.

Illustration for Cloud Tasks vs Pub/Sub on Google Cloud

Cloud Tasks and Pub/Sub both move work off the request path on Google Cloud, and both retry with at-least-once delivery, which is why the choice between them often gets made by whichever one the first tutorial used. They are built for different jobs: Cloud Tasks queues a call to one specific endpoint and lets the producer control when and how fast it runs, while Pub/Sub publishes an event that any number of subscribers can react to without the publisher knowing about them.

This comparison covers the limits that decide between them, using Google's own feature table, and how Encore gives you Pub/Sub on GCP from a topic declared in your backend code.

Cloud Tasks vs Pub/Sub at a glance

The Cloud Tasks and Pub/Sub columns follow Google's Choosing Pub/Sub or Cloud Tasks page.

Encore Pub/SubCloud TasksPub/Sub
InvocationImplicit, typed topic in codeExplicit, one target per taskImplicit, publisher does not know consumers
On GCPPub/Sub topic and subscriptionsCloud Tasks queuePub/Sub
Consumers per messageAny number of subscriptionsOneAny number of subscriptions
Scheduled deliveryNot built in, use a cron job for periodic workYesNo
Creation deduplicationIdempotent handlersYesby task nameNo
Rate controlmaxConcurrency per subscriptionPer-queue dispatch rateFlow control in pull clients
Max message size10 MB (Pub/Sub)1 MB10 MB
Max delivery ratePub/Sub regional quotas500 QPS per queueNo upper limit, regional quotas apply
OrderingOrdering keys supportedBest effortOrdering keys
Local developmentRuns with encore runEmulators are community-builtOfficial emulator

How does Encore handle Pub/Sub on GCP?

Encore

Encore combines an open source infrastructure SDK with a platform that provisions and deploys into your own AWS or GCP account. Topics and subscriptions are declared in TypeScript or Go next to the code that publishes and consumes them, and on GCP Encore creates the Pub/Sub topic and subscriptions in your project and gives each service a service account that can only publish or consume what it uses, as the GCP infrastructure docs describe.

Set up the app

Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

~
$ encore app create shop --example=ts/hello-world$ cd shop && mkdir -p orders receipts
// orders/orders.ts import { api } from "encore.dev/api"; import { Topic } from "encore.dev/pubsub"; export interface OrderPlaced { orderId: string; email: string; totalCents: number; } // A Pub/Sub topic on GCP, SNS and SQS on AWS. export const orderPlaced = new Topic<OrderPlaced>("order-placed", { deliveryGuarantee: "at-least-once", }); export const place = api( { expose: true, method: "POST", path: "/orders" }, async (o: OrderPlaced): Promise<{ messageId: string }> => { const messageId = await orderPlaced.publish(o); return { messageId }; }, );

The receipts service consumes the topic. maxConcurrency caps how many messages it handles at once, which covers the common Cloud Tasks reason of not overwhelming a downstream email API, and the retry policy backs off before a message lands in the dead-letter queue:

// receipts/receipts.ts import { Subscription } from "encore.dev/pubsub"; import { orderPlaced } from "../orders/orders"; const _ = new Subscription(orderPlaced, "send-receipt", { maxConcurrency: 10, ackDeadline: "60s", retryPolicy: { minBackoff: "10s", maxBackoff: "10m", maxRetries: 8 }, handler: async (o) => { // Delivery is at least once: key the send on o.orderId so a retry // does not email the customer twice. console.log("sending receipt", o.orderId); }, });

A second consumer, such as an analytics service that records the order, is another Subscription in its own service, and it gets its own copy of every event with no change to the publisher, which is the part Cloud Tasks cannot do. encore run runs topics and subscriptions locally, so the publish and both handlers appear in one trace, and the Pub/Sub docs cover ordering keys, attributes and exactly-once topics.

A coding agent adding a consumer works in one file and tests it against the local topic before review, with no IAM binding or push endpoint to set up in the GCP console. The same code deploys to AWS as SNS and SQS if the app ever moves.

Every pull request can get a preview environment with its own topic and subscription, and the local development dashboard shows each published message and the subscriber call in one trace.

Best fit: GCP backends where events flow between your own services and you want Pub/Sub topics, subscriptions, dead-letter handling and service accounts set up in your project from the code.

Cloud Tasks

Cloud Tasks

A Cloud Tasks queue holds tasks that each target one HTTP endpoint, typically a Cloud Run service, with an OIDC token for authentication. The producer decides everything about execution: scheduleTime delays a task by minutes or days, a task name deduplicates creation so a retried request does not enqueue twice, and the queue's maxDispatchesPerSecond and maxConcurrentDispatches keep a fragile downstream API from being flooded. HTTP targets can run for up to 30 minutes per attempt.

The limits are Google's: 500 dispatches per second per queue, a 1 MB task size and one handler per task. Fanning one event out to three services means creating three tasks, and the producer has to know every consumer's URL. Each queue and its IAM (the service account that creates tasks, roles/run.invoker for the token's identity) is configured outside the application, and there is no official local emulator, so tests usually call the handler directly.

Best fit: Delayed or rate-limited calls to one endpoint, such as reminder emails due in an hour or syncs against an API that allows ten requests per second.

Pub/Sub

Pub/Sub

Pub/Sub decouples publishers from subscribers: each subscription gets every message, push subscriptions call an HTTPS endpoint and pull subscriptions let workers fetch at their own pace. It accepts messages up to 10 MB, has no fixed per-topic delivery rate beyond regional quotas, supports ordering keys and dead-letter topics, and retains messages for up to 31 days. Google ships an official emulator for local development.

What it does not do is control execution: there is no scheduled delivery and no deduplication at publish time, so delays live in your code and handlers must be idempotent. Push subscriptions also need an endpoint, an authenticated service account and a dead-letter topic with its own IAM grants, which is the setup Encore handles from the subscription declaration.

Best fit: Events with several consumers, high-throughput ingestion, and any flow where the publisher should not know who reacts.

How to choose

Pick Encore when the work is events between your own services on GCP and you want Pub/Sub topics and subscriptions provisioned from code, with concurrency limits and retries declared next to the handler and a local loop that runs everything. Pick Cloud Tasks when one endpoint must be called at a specific time or a strict rate. Pick Pub/Sub directly when a platform team owns topics and subscriptions and other systems publish to them.

Frequently asked questions

What is the difference between Cloud Tasks and Pub/Sub?

Cloud Tasks is explicit invocation: the producer creates a task aimed at one HTTP endpoint and controls when and how fast it runs, with scheduling, deduplication by task name and per-queue rate limits. Pub/Sub is implicit invocation: the publisher sends an event to a topic without knowing who consumes it, and every subscription gets its own copy.

When should I use Cloud Tasks instead of Pub/Sub?

Use Cloud Tasks when one specific endpoint must be called later or at a controlled rate, such as calling a rate-limited third-party API, delaying a reminder by an hour, or deduplicating task creation. Use Pub/Sub when an event should reach several independent consumers or when volume can exceed 500 dispatches per second per queue.

How do I use Pub/Sub on GCP with Encore?

Declare a topic with new Topic<OrderPlaced>("order-placed", { deliveryGuarantee: "at-least-once" }), publish with orderPlaced.publish(event), and add consumers with new Subscription(orderPlaced, "send-receipt", { handler, maxConcurrency: 10 }). On GCP, Encore creates the Pub/Sub topic and subscriptions in your own project and grants each service only the access it needs.

Can Pub/Sub rate limit deliveries like Cloud Tasks?

Pub/Sub has no per-queue dispatch rate, but pull subscribers can use flow control and push subscriptions slow down when the endpoint returns errors. Limiting concurrency in the subscriber caps how many messages are processed at once.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders