GCP Cloud Functions (2nd Gen) & Eventarc ⚡📨

Google Cloud Functions (2nd Gen) is Google’s next-generation Function-as-a-Service (FaaS) platform. Re-architected from the ground up, Cloud Functions (2nd Gen) runs directly on top of Google Cloud Run and Eventarc, transforming simple developer code into containerized, high-concurrency serverless microservices.


Architecture & Mental Model

Cloud Functions 2nd Gen Architecture Stack

Unlike 1st Gen functions (which ran on legacy App Engine infrastructure), 2nd Gen functions are compiled into OCI container images via Google Cloud Build and executed on Cloud Run:

┌────────────────────────────────────────────────────────────────────────┐
│                        Developer Source Code                           │
│          (Python, Node.js, Go, Java, .NET, Ruby, PHP)                  │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ gcloud functions deploy
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                        Google Cloud Build                              │
│   Uses open-source Buildpacks to package code into an OCI image        │
│   and pushes to Artifact Registry (us-docker.pkg.dev/...)              │
└───────────────────────────────────┬────────────────────────────────────┘
                                    │ Deploys container
                                    ▼
┌────────────────────────────────────────────────────────────────────────┐
│                   Underlying Cloud Run Service                         │
│                                                                        │
│   • Request Concurrency: Up to 1,000 requests per instance (Def: 1)    │
│   • Execution Timeout: Up to 60 minutes for HTTP functions             │
│   • CPU/Memory Sizing: Up to 8 vCPU and 32 GiB RAM                     │
│   • Traffic Splitting: Native canary revisions (e.g. 90/10 split)      │
└───────────────────────────────────▲────────────────────────────────────┘
                                    │ Invokes
                                    │
┌───────────────────────────────────┴────────────────────────────────────┐
│                             Eventarc                                   │
│   Standardized CNCF CloudEvents v1.0 Delivery Engine:                  │
│   • Direct Cloud Storage mutations (object.finalize)                   │
│   • Cloud Pub/Sub message publishing                                   │
│   • 130+ GCP services via Cloud Audit Log event filtering             │
└────────────────────────────────────────────────────────────────────────┘

1st Gen vs. 2nd Gen Comparison

Architectural Dimension1st Gen Functions (Legacy)2nd Gen Functions (Modern Standard)
Underlying InfrastructureApp Engine internal runtimeGoogle Cloud Run
Event Routing EngineLegacy proprietary event brokerEventarc (CNCF CloudEvents v1.0)
Concurrency per InstanceStrictly 1 request at a timeUp to 1,000 concurrent requests
Max Request Timeout9 minutes (540 seconds)60 minutes (3,600s) for HTTP
Max Memory & CPU8 GiB RAM / 2 vCPUs32 GiB RAM / 8 vCPUs
Traffic SplittingNot supportedSupported natively (Canary rollouts)
Direct VPC EgressRequires Serverless VPC AccessDirect VPC Egress supported

Core Concepts

1. Concurrency Tuning in Serverless FaaS

In AWS Lambda and 1st Gen Cloud Functions, if 100 simultaneous requests arrive, the cloud provider spins up 100 independent container instances, triggering 100 separate cold starts and risking database connection pool exhaustion.

  • In Cloud Functions 2nd Gen, setting --concurrency=80 allows a single warm function instance to process 80 requests simultaneously.
  • Dramatically slashes compute costs and eliminates cold starts for concurrent traffic.

2. Eventarc & CloudEvents Specification

All asynchronous event-driven functions in 2nd Gen receive payloads structured according to the CNCF CloudEvents v1.0 specification:

{
  "specversion": "1.0",
  "type": "google.cloud.storage.object.v1.finalized",
  "source": "//storage.googleapis.com/projects/_/buckets/my-prod-bucket",
  "id": "1234567890",
  "time": "2026-09-06T12:00:00Z",
  "datacontenttype": "application/json",
  "data": {
    "bucket": "my-prod-bucket",
    "name": "invoices/invoice-001.pdf",
    "size": "45210"
  }
}
  • Uniform Developer Experience: Whether an event originates from a Cloud Storage upload, a BigQuery table creation, or a Firebase user sign-up, the envelope format is identical.

3. Cold Start Optimization

  • Min Instances (--min-instances=1): Keeps a pre-warmed instance constantly provisioned to eliminate cold starts for latency-sensitive customer APIs.
  • Buildpack Optimization: Keep dependency manifests (package.json, requirements.txt) lean. Heavy libraries (like Pandas, PyTorch, or TensorFlow) dramatically increase container initialization time.

Production gcloud CLI Commands

1. Deploying a High-Concurrency HTTP Function with Direct VPC Egress

gcloud functions deploy user-service \
  --gen2 \
  --runtime=python311 \
  --region=us-central1 \
  --source=./src \
  --entry-point=handle_request \
  --trigger-http \
  --allow-unauthenticated \
  --concurrency=80 \
  --cpu=1 \
  --memory=512Mi \
  --min-instances=1 \
  --max-instances=20 \
  --timeout=60s \
  --network=prod-vpc \
  --subnet=prod-us-central1 \
  --vpc-egress=private-ranges-only \
  --set-secrets="API_KEY=projects/123456789012/secrets/api-key:latest" \
  --service-account=func-runner@my-prod-project.iam.gserviceaccount.com

2. Deploying an Event-Driven Function Triggered by Cloud Storage via Eventarc

gcloud functions deploy thumbnail-generator \
  --gen2 \
  --runtime=nodejs20 \
  --region=us-central1 \
  --source=./thumbnail-src \
  --entry-point=generateThumbnail \
  --trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
  --trigger-event-filters="bucket=prod-raw-images" \
  --memory=1Gi \
  --timeout=120s \
  --service-account=func-runner@my-prod-project.iam.gserviceaccount.com

3. Python Sample: Processing a CloudEvent Payload

import functions_framework
from cloudevents.http import CloudEvent
 
@functions_framework.cloud_event
def generate_thumbnail(cloudevent: CloudEvent):
    # Extract CloudEvent metadata and data payload
    event_type = cloudevent["type"]
    data = cloudevent.data
 
    bucket_name = data["bucket"]
    file_name = data["name"]
    file_size = data["size"]
 
    print(f"Received event: {event_type}")
    print(f"Processing newly created object: gs://{bucket_name}/{file_name} ({file_size} bytes)")
 
    # Execute image processing logic...
    return "OK", 200

Quotas & Limits

ParameterLimitProduction Notes
Max HTTP execution timeout60 minutes (3,600s)Configurable up from 1st Gen 9-min limit
Max event-driven timeout10 minutes (600s)For Eventarc background triggers
Max function memory32 GiBUp to 8 vCPUs
Max request concurrency1,000 per instanceDefault is 1; tune according to I/O vs CPU
Max deployment size500 MB (compressed)Store heavy model weights in Cloud Storage

References


Pricing Examples

Scenario 1: Event-Driven Image Thumbnail Generation

  • 500,000 image uploads per month triggering a 2nd Gen function.
  • Execution time: 800 ms per invocation. Allocation: 1 vCPU, 512 MB RAM.
  • Total vCPU-seconds: 500,000 × 1 vCPU × 0.8s = 400,000 vCPU-seconds.
  • Monthly Free Tier: First 2 million invocations, 400,000 vCPU-seconds, and 200,000 GB-seconds are 100% free every month.
  • Total Monthly Bill: $0.00 / month (Falls entirely within the permanent free tier).

Scenario 2: High-Throughput Webhook Ingestion API

  • 50 million inbound webhook requests per month with average latency of 150 ms.
  • Concurrency tuned to 50 requests per instance.
  • Billable compute: (50M reqs × 0.15s) / 50 = 150,000 instance-seconds.
  • Invocation requests fee (after 2M free): 48M × 19.20.
  • Active vCPU/RAM compute time: ~$5.50.
  • 1 Pre-warmed min-instance (--min-instances=1) to eliminate cold starts: ~$6.50 / month.
  • Total Monthly Cost: ~$31.20 / month (Handling 50M webhooks with zero cold starts).

Nuggets & Gotchas

  1. 2nd Gen Functions Appear in the Cloud Run Console: Because 2nd Gen functions compile directly to Cloud Run services, they will appear in both the Cloud Functions console and the Cloud Run console. If an operator edits the service configuration directly in Cloud Run, those changes can be wiped out on the next gcloud functions deploy execution. Always manage configuration via the Functions CLI or Terraform.
  2. The CloudEvent finalized Loop Disaster: If an event-driven function is triggered by google.cloud.storage.object.v1.finalized on Bucket A, and the function’s code writes an output file or thumbnail back to Bucket A, the newly written file will trigger another finalized event! This creates an infinite recursive execution loop that can burn thousands of dollars in minutes. Always write output files to a separate destination bucket (e.g. Bucket B).
  3. Missing Eventarc Service Agent Permissions: When deploying an event-driven function for the first time, Eventarc requires permission to publish events from your services. If you see FAILED_PRECONDITION: Eventarc Service Agent lacks roles/eventarc.serviceAgent, you must explicitly grant the service agent role or allow GCP to auto-generate it.
  4. Default Concurrency is 1 (Not Cloud Run’s 80): When deploying a service directly via Cloud Run, concurrency defaults to 80. However, when deploying via gcloud functions deploy --gen2, concurrency defaults to 1 to maintain backwards compatibility with 1st Gen single-threaded behavior! To take advantage of multi-request cost savings, you must explicitly pass --concurrency=80.
  5. Cold Starts on Min-Instances Scaling: Setting --min-instances=1 ensures that the first instance is warm. However, if traffic suddenly bursts to 50 concurrent requests and your function has --concurrency=1, Cloud Run must provision 49 new instances simultaneously. All 49 new instances will experience cold starts. Tune --concurrency alongside --min-instances.

Across the wiki