Articles Platform Engineering

Event-Driven Microservices with Cloud Pub/Sub and Eventarc on Cloud Run

🎧 Listen to Article Client-side voice reader powered by Web Speech API.
Ready to play
Speed:

Event-Driven Microservices with Cloud Pub/Sub and Eventarc on Cloud Run

Synchronous HTTP request-response cycles are poorly suited for heavy operations like high-definition audio generation, image resizing, and PDF rendering. Offloading long-running work to asynchronous background event consumers keeps user-facing APIs responsive.

In AustinSS Blogs, audio article reader generation (Google Cloud Text-to-Speech Journey voices) and media processing are designed around Eventarc and Cloud Pub/Sub.


1. Cloud Storage Eventarc Triggers

When an author uploads a hero banner image or media asset, a Cloud Storage google.cloud.storage.object.v1.finalized event triggers our background processing worker via Eventarc:

resource "google_eventarc_trigger" "image_processor" {
  name     = "trigger-image-processor"
  location = "us-central1"

  matching_criteria {
    attribute = "type"
    value     = "google.cloud.storage.object.v1.finalized"
  }
  matching_criteria {
    attribute = "bucket"
    value     = "austinss-blog-media-dev"
  }

  destination {
    cloud_run_service {
      service = "austinss-blog-worker"
      region  = "us-central1"
    }
  }

  service_account = google_service_account.eventarc_invoker.email
}

2. Handling CloudEvents in FastAPI

Cloud Run receives events formatted as standard CloudEvents HTTP POST payloads:

from fastapi import APIRouter, Header, Request

router = APIRouter()

@router.post("/events/media-uploaded")
async def handle_media_event(
    request: Request,
    ce_type: str = Header(alias="ce-type"),
    ce_source: str = Header(alias="ce-source"),
):
    if ce_type == "google.cloud.storage.object.v1.finalized":
        event_data = await request.json()
        bucket = event_data["bucket"]
        object_name = event_data["name"]
        # Trigger background image compression or audio synthesis
        return {"status": "accepted", "object": object_name}
    return {"status": "ignored"}

This guarantees sub-50ms user response times while processing compute-heavy background tasks on demand.