Writing and Responding to Pub/Sub Messages

Region ID

The REGION_ID is an abbreviated code that Google assigns based on the region you select when you create your app. The code does not correspond to a country or province, even though some region IDs may appear similar to commonly used country and province codes. Including REGION_ID.r in App Engine URLs is optional for existing apps and will soon be required for all new apps.

To ensure a smooth transition, we are slowly updating App Engine to use region IDs. If we haven't updated your Google Cloud project yet, you won't see a region ID for your app. Since the ID is optional for existing apps, you don't need to update URLs or make other changes once the region ID is available for your existing apps.

Learn more about region IDs.

Pub/Sub provides reliable, many-to-many, asynchronous messaging between applications. Publisher applications can send messages to a topic, and other applications can subscribe to that topic to receive the messages.

This document describes how to use the Cloud Client Library to send and receive Pub/Sub messages in a Go app.


  • Follow the instructions in "Hello, World!" for Go on App Engine to set up your environment and project, and to understand how App Engine Go apps are structured.
  • Write down and save your project ID, because you will need it to run the sample application described in this document.

    Cloning the sample app

    Copy the sample apps to your local machine, and navigate to the pubsub directory:

    go get -u -d -v github.com/GoogleCloudPlatform/golang-samples/pubsub
    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/appengine_flexible/pubsub

    Creating a topic and subscription

    Create a topic and subscription, which includes specifying the endpoint to which the Pub/Sub server should send requests:

    gcloud pubsub topics create YOUR_TOPIC_NAME
    gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
        --topic YOUR_TOPIC_NAME \
        --push-endpoint \
        https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/pubsub/push?token=YOUR_TOKEN \
        --ack-deadline 10

    Replace YOUR_TOKEN with a secret random token. The push endpoint uses this to verify requests.

    Setting environment variables

    Edit the app.yaml file to set the environment variables for your topic and verification token:

      PUBSUB_TOPIC: your-topic
      # This token is used to verify that requests originate from your
      # application. It can be any sufficiently random string.

    Code review

    The sample app uses the Google Cloud Pub/Sub Client Library.

    The sample app uses the environment variables you set in the app.yaml file (PUBSUB_TOPIC and PUBSUB_VERIFICATION_TOKEN) for configuration.

    The messages received by this instance are stored in a slice:

    messages   []string

    The pushHandler function receives pushed messages, verifies the token, and adds the message to the messages slice:

    func pushHandler(w http.ResponseWriter, r *http.Request) {
    	// Verify the token.
    	if r.URL.Query().Get("token") != token {
    		http.Error(w, "Bad token", http.StatusBadRequest)
    	msg := &pushRequest{}
    	if err := json.NewDecoder(r.Body).Decode(msg); err != nil {
    		http.Error(w, fmt.Sprintf("Could not decode body: %v", err), http.StatusBadRequest)
    	defer messagesMu.Unlock()
    	// Limit to ten.
    	messages = append(messages, string(msg.Message.Data))
    	if len(messages) > maxMessages {
    		messages = messages[len(messages)-maxMessages:]

    The publishHandler function publishes new messages to the topic.

    func publishHandler(w http.ResponseWriter, r *http.Request) {
    	ctx := context.Background()
    	msg := &pubsub.Message{
    		Data: []byte(r.FormValue("payload")),
    	if _, err := topic.Publish(ctx, msg).Get(ctx); err != nil {
    		http.Error(w, fmt.Sprintf("Could not publish message: %v", err), 500)
    	fmt.Fprint(w, "Message published.")

    Running the sample locally

    When running locally, you can use the Cloud SDK to provide authentication to use Google Cloud APIs. Assuming you set up your environment as described in Prerequisites, you have already run the gcloud init command, which provides this authentication.

    Then set environment variables before starting your application:

    export GOOGLE_CLOUD_PROJECT=[your-project-id]
    export PUBSUB_VERIFICATION_TOKEN=[your-token]
    export PUBSUB_TOPIC=[your-topic]
    go run pubsub.go

    Simulating push notifications

    The application can send messages locally, but it is not able to receive push messages locally. You can, however, simulate a push message by making an HTTP request to the local push notification endpoint. The sample includes the file sample_message.json.

    You can use curl or a httpie client to send an HTTP POST request:

    curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[your-token]"


    http POST ":8080/pubsub/push?token=[your-token]" < sample_message.json


    HTTP/1.1 200 OK
    Date: Tue, 13 Nov 2018 16:04:18 GMT
    Content-Length: 0

    After the request completes, you can refresh localhost:8080 and see the message in the list of received messages.

    Running on App Engine

    To deploy the demo app to App Engine by using the gcloud command-line tool, you run the following command from the directory where your app.yaml file is located:

    gcloud app deploy

    You can now access the application at https://PROJECT_ID.REGION_ID.r.appspot.com. You can use the form to submit messages, but there's no guarantee of which instance of your application will receive the notification. You can send multiple messages and refresh the page to see the received message.