What Is Cloud Functions? Google Cloud Functions Explained

Cloud Functions is GCP’s serverless platform for running code in response to events. No servers to provision, no containers to build, no infrastructure to manage. You write a function, choose a trigger, and deploy from source. GCP handles everything else: scaling, patching, and routing. It is the fastest path from “I need to react to this event” to working code in production on GCP, and the right tool for webhooks, event handlers, and lightweight automation tasks.

Cloud Functions in simple terms

Think of Cloud Functions like a light switch that triggers an action. When something flips the switch — an HTTP request arrives, a file lands in a storage bucket, a message appears in a queue — your function runs, does its work, and stops. You do not need to think about the wiring behind the wall.

The key difference from a regular web server: nothing runs between events. There is no always-on process waiting for work. When an event arrives, GCP starts your function (or reuses a warm instance if one is available), runs your code, and returns the result. When no events arrive, you pay nothing.

This is “serverless” in the most direct sense. The servers exist, but you never see them. Google manages them. Your job is to write the code that responds to the event.

Analogy

A Cloud Function is like a vending machine. It sits idle until someone presses a button (the trigger). When the button is pressed, it does its job and then waits again. You do not need to hire someone to stand at the machine between customers. It just responds when needed.

What is Cloud Functions?

Cloud Functions is a serverless, event-driven compute service on Google Cloud. You deploy individual functions — single-purpose pieces of code — that run in response to triggers. You do not write a full application or web server. You write a handler for one specific task: process this upload, respond to this HTTP request, handle this Pub/Sub message.

Cloud Functions supports multiple runtimes including Python, Node.js, Go, Java, Ruby, PHP, and .NET. You deploy from source code directly with no Dockerfile required. GCP builds and manages the container for you.

Under the hood, Cloud Functions 2nd gen is built on Cloud Run. The infrastructure model is the same, but Cloud Functions provides a higher level of abstraction: you think about functions, not services or containers. When you need more control — custom runtimes, multiple routes, system-level dependencies — Cloud Run gives you that at the cost of managing a Dockerfile.

  • Deployment model: deploy from source code; no container registry needed
  • Scaling: scales to zero at no cost; scales up automatically with load
  • Billing: billed per invocation and per CPU/memory during execution
  • Infrastructure: Google manages patching, scaling, and runtime updates
  • Supported runtimes: Python, Node.js, Go, Java, Ruby, PHP, .NET

How Cloud Functions works

Every Cloud Function invocation follows the same basic flow:

  1. An event happens. An HTTP request arrives, a Pub/Sub message is published, a file is uploaded to Cloud Storage, or another trigger fires.
  2. GCP routes the event. Cloud Functions (via Eventarc for 2nd gen) receives the event and identifies which function should handle it.
  3. An instance starts or is reused. If a warm instance from a previous invocation is available, GCP reuses it. If not, it starts a new one. That startup delay is called a cold start and typically adds a few hundred milliseconds to a couple of seconds.
  4. Your code runs. The function handler executes with the event data passed as input.
  5. The result is returned or work is performed. HTTP functions return a response. Background functions (Pub/Sub, Storage) perform side effects like writing to a database or calling an external API.

If your function throws an unhandled exception, the invocation is marked as failed. For Pub/Sub and other background triggers, GCP retries the event automatically. For HTTP triggers, the error is returned to the caller.

Cold start explained

Imagine a restaurant where the kitchen closes between lunch and dinner. When the first dinner guest arrives, the chef has to prep everything from scratch before cooking. That wait is the cold start. Once the kitchen is running, subsequent guests get their food quickly. Cloud Functions works the same way: the first request after idle time takes longer, but everything after it is fast.

Tip

To eliminate cold starts for latency-sensitive functions, use —min-instances=1 at deploy time. This keeps one warm instance running at all times. You pay for that instance even at zero traffic, but the first request of the day is instant.

Cloud Functions 1st gen vs 2nd gen

Always use 2nd gen for new deployments. It runs on Cloud Run under the hood, has significantly higher limits, and supports concurrency, meaning one instance can handle multiple requests simultaneously instead of spinning up a new instance for every single request.

Feature1st gen2nd gen
Max timeout9 minutes60 minutes
Max memory8 GB32 GB
Concurrency1 request per instanceUp to 1,000 per instance
Traffic splittingNoYes
Minimum instancesNoYes
Underlying platformProprietary runtimeBuilt on Cloud Run
Eventarc trigger supportLimitedFull (90+ event sources)
Why concurrency matters

In 1st gen, if 50 requests arrive simultaneously, GCP starts 50 separate instances. In 2nd gen, a single instance can handle up to 1,000 concurrent requests. That means far fewer cold starts and significantly lower cost under load. Unless you are maintaining an existing 1st gen function, use 2nd gen.

When to use Cloud Functions

Cloud Functions works best for focused, event-driven tasks where you want minimal deployment overhead. Common good fits:

  • Webhooks — receive HTTP callbacks from Stripe, GitHub, or Slack and perform an action in response.
  • Lightweight APIs — a small number of HTTP endpoints that do simple data lookups or transformations.
  • Background processing from Pub/Sub — consume messages from a topic and process them asynchronously: send emails, update records, trigger downstream workflows.
  • File processing on upload — resize images, validate CSVs, or extract data from files as soon as they land in Cloud Storage.
  • Simple automation — run a script on a schedule via Cloud Scheduler and an HTTP trigger, or react to a resource change in Cloud Audit Logs.
  • Event-driven integrations — a Firestore document change triggers a notification, a BigQuery job completion triggers a downstream report.
Quick rule

If you can describe your task in one sentence starting with “when X happens, do Y”, Cloud Functions is probably the right tool. If you need to describe multiple routes or complex logic, look at Cloud Run instead.

When Cloud Functions is not the best choice

Cloud Functions has real constraints. These situations call for a different tool:

  • Multi-route HTTP APIs. If you are building an API with many endpoints, routing middleware, or authentication layers, use Cloud Run instead. Cloud Functions is optimised for a single handler, not a full API server.

  • Custom runtimes or system dependencies. Cloud Functions supports a fixed set of runtimes. If you need a runtime version not on the supported list, a compiled binary, or low-level system access, Cloud Run lets you control the container entirely.

  • Long-running or complex workloads. Cloud Functions 2nd gen has a maximum timeout of 60 minutes. For batch jobs or multi-step workflows that run longer, use Cloud Run Jobs, Cloud Batch, or Cloud Workflows.

  • Persistent background workers. Cloud Functions is not designed to run indefinitely. A process that polls a queue or runs a continuous loop belongs on a VM or GKE.

  • Full container control. If you want to own the Dockerfile, set infrastructure-level configuration, or use traffic splitting across revisions more granularly, use Cloud Run directly.

Cloud Functions vs Cloud Run

This is the most common question beginners have. Both are serverless, both scale to zero, and Cloud Functions 2nd gen is built on Cloud Run under the hood. The difference is in abstraction level and deployment model.

DimensionCloud FunctionsCloud Run
Unit of deploymentA single function handlerA containerised service (many routes)
Deployment modelDeploy from source code directlyBuild and push a container image
Dockerfile requiredNoYes
Runtime flexibilitySupported runtimes onlyAny language, any binary
HTTP routingSingle endpoint per functionFull router (GET /users, POST /orders, etc.)
Concurrency (2nd gen)Up to 1,000 per instanceUp to 1,000 per instance
Max timeout60 minutes60 minutes (services); no limit (jobs)
Best fitWebhooks, event handlers, simple APIsFull APIs, custom runtimes, complex services
Which should I pick?

If you are writing one function that responds to one trigger, use Cloud Functions. It deploys faster and requires no container knowledge. If you are building something with multiple routes, a complex runtime, or you already know Docker, use Cloud Run. When in doubt, start with Cloud Functions. You can always migrate to Cloud Run later.

For more on this decision, see:

Common Cloud Functions trigger types

A trigger is the event that causes your function to run. Cloud Functions 2nd gen supports all of the following:

  • HTTP — your function is exposed as an HTTPS endpoint. Any system that can make an HTTP request can call it: a browser, a third-party webhook, a cron job via Cloud Scheduler. This is the most flexible trigger type.

  • Pub/Sub — your function runs whenever a message is published to a specific topic. Used for decoupled asynchronous processing: one service publishes events, your function consumes them.

  • Cloud Storage — your function runs when a file is uploaded, deleted, archived, or modified in a bucket. Used for file processing pipelines.

  • Eventarc — the underlying event routing layer for 2nd gen. Supports 90+ GCP services including Cloud Audit Logs and BigQuery. When you set —trigger-event-filters in a 2nd gen deployment, GCP creates an Eventarc trigger under the hood.

  • Firestore / Firebase — functions can react to document creates, updates, and deletes in Firestore. Commonly used in Firebase apps to run server-side logic in response to database changes.

See Event-Driven Patterns with Cloud Functions for deeper coverage of each trigger type, chaining functions together with Pub/Sub, and idempotency requirements.

HTTP-triggered functions

An HTTP function is exposed as an HTTPS endpoint. The example below returns a greeting based on a query parameter. Add —allow-unauthenticated to make it publicly accessible, or omit that flag to require a valid Google identity token.

# main.py
import functions_framework

@functions_framework.http
def hello(request):
    name = request.args.get("name", "World")
    return f"Hello, {name}!", 200
# Deploy an HTTP function (2nd gen)
gcloud functions deploy hello \
  --gen2 \
  --runtime=python312 \
  --region=us-central1 \
  --source=. \
  --entry-point=hello \
  --trigger-http \
  --allow-unauthenticated

# Get the function URL
gcloud functions describe hello \
  --gen2 \
  --region=us-central1 \
  --format="value(serviceConfig.uri)"

Pub/Sub-triggered functions

Pub/Sub triggers run your function when a message is published to a topic. Write Pub/Sub functions to be idempotent. If the function throws an exception, Pub/Sub retries delivery and the same message may be processed more than once.

# main.py
import base64
import functions_framework

@functions_framework.cloud_event
def process_message(cloud_event):
    data = base64.b64decode(cloud_event.data["message"]["data"]).decode()
    print(f"Received message: {data}")
    # Write to a database or call an API here
    # If this raises an exception, Pub/Sub retries — make it safe to run twice
# Deploy a Pub/Sub triggered function
gcloud functions deploy process-message \
  --gen2 \
  --runtime=python312 \
  --region=us-central1 \
  --source=. \
  --entry-point=process_message \
  --trigger-topic=my-topic
Idempotency

Pub/Sub guarantees at-least-once delivery. If your function sends an email, inserts a database row, or charges a customer, it must check whether the work was already done before doing it again. Use the Pub/Sub message ID as a deduplication key, or use an upsert instead of an insert.

Cloud Storage-triggered functions

Storage triggers fire when a file is uploaded, deleted, or modified in a bucket. The google.cloud.storage.object.v1.finalized event fires when an upload completes. Use it to process files as they arrive.

# main.py — triggered when a file upload completes
import functions_framework
from google.cloud import storage

@functions_framework.cloud_event
def process_upload(cloud_event):
    data = cloud_event.data
    bucket = data["bucket"]
    name = data["name"]
    print(f"Processing: gs://{bucket}/{name}")
    client = storage.Client()
    blob = client.bucket(bucket).blob(name)
    content = blob.download_as_text()
    # Process content and write output to a different bucket
# Deploy with a Cloud Storage trigger
gcloud functions deploy process-upload \
  --gen2 \
  --runtime=python312 \
  --region=us-central1 \
  --source=. \
  --entry-point=process_upload \
  --trigger-event-filters="type=google.cloud.storage.object.v1.finalized" \
  --trigger-event-filters="bucket=my-uploads-bucket" \
  --service-account=process-fn-sa@PROJECT_ID.iam.gserviceaccount.com
Trigger loop

If your function writes output to the same bucket that triggered it, the new file triggers the function again, creating an infinite loop. Always write output to a different bucket, or check the file name prefix and return early for files your function produced.

Environment variables and secrets

Use plain environment variables for non-sensitive configuration. Use Secret Manager for any value you would not want in source code: database passwords, API keys, tokens. Never pass secrets as plain environment variable values that end up in deployment configs or version control.

# Non-sensitive config via environment variables
gcloud functions deploy hello \
  --gen2 \
  --runtime=python312 \
  --region=us-central1 \
  --source=. \
  --entry-point=hello \
  --trigger-http \
  --set-env-vars=APP_ENV=production,LOG_LEVEL=info

# Sensitive values via Secret Manager
gcloud functions deploy hello \
  --gen2 \
  --runtime=python312 \
  --region=us-central1 \
  --source=. \
  --entry-point=hello \
  --trigger-http \
  --set-secrets=DB_PASSWORD=db-password:latest \
  --service-account=hello-fn-sa@PROJECT_ID.iam.gserviceaccount.com
Default service account

Cloud Functions uses the Compute Engine default service account by default, which has project Editor permissions — far more access than any function needs. Create a dedicated service account and specify it with —service-account for any function that accesses real data or secrets. See Principle of Least Privilege, Why Service Account Keys Are Dangerous, and Service Account Impersonation for guidance on service account best practices.

Testing functions locally

The Functions Framework lets you run your function locally before deploying. A full deploy-to-GCP cycle takes a minute or more. Local testing catches bugs faster and costs nothing. Install it once, then run your function against it as many times as you need.

# Install the Functions Framework
pip install functions-framework

# Run locally on port 8080
functions-framework --target=hello --port=8080

# Test in another terminal
curl "http://localhost:8080?name=World"

# Test a Pub/Sub-triggered function with a CloudEvent payload
curl -X POST http://localhost:8080 \
  -H "Content-Type: application/json" \
  -H "ce-specversion: 1.0" \
  -H "ce-type: google.cloud.pubsub.topic.v1.messagePublished" \
  -H "ce-source: //pubsub.googleapis.com/projects/my-project/topics/my-topic" \
  -H "ce-id: 1234" \
  -d '{"message": {"data": "aGVsbG8gd29ybGQ="}}'
Note

The base64 value in the Pub/Sub example decodes to “hello world”. Always base64-encode message data in test payloads to match what the live Pub/Sub service delivers.

Common beginner mistakes

  1. Using 1st gen for new functions. 2nd gen has a 60-minute timeout, higher memory, concurrency up to 1,000, traffic splitting, and full Eventarc support. There is no reason to use 1st gen for new deployments. Always add —gen2.

  2. Not making Pub/Sub-triggered functions idempotent. When a function throws an exception, Pub/Sub retries delivery. The same message may be processed multiple times. If your function inserts a database row, sends an email, or charges a customer, check whether the work was already done before doing it again.

  3. Writing to the same bucket that triggered the function. This creates a trigger loop. Every output file becomes a new input. Write to a separate output bucket or check the file name before processing.

  4. Using the default service account. The Compute Engine default service account has project Editor permissions. Use a dedicated service account with only the roles the function actually needs.

  5. Using Cloud Functions when Cloud Run is the better fit. Cloud Functions is excellent for single-purpose handlers. If you find yourself adding more and more routes to one function or fighting the runtime constraints, step up to Cloud Run.

Frequently asked questions

When should I use Cloud Functions instead of Cloud Run?

Use Cloud Functions when you have a single-purpose event handler, webhook, or simple API endpoint and you want source-based deployment without writing a Dockerfile. You write a function, GCP handles the container. Use Cloud Run when you need a multi-route HTTP service, a custom runtime or binary, or system-level dependencies. Cloud Functions 2nd gen runs on Cloud Run under the hood, so limits are similar, but Cloud Run gives you more control at the cost of managing a Dockerfile.

What is the difference between Cloud Functions 1st gen and 2nd gen?

Use 2nd gen for all new deployments. Key improvements: maximum timeout increases from 9 minutes to 60 minutes, memory limit increases from 8 GB to 32 GB, concurrency support goes from 1 request per instance to up to 1,000, and traffic splitting between function versions is available. 2nd gen functions are backed by Cloud Run and expose the underlying Cloud Run service for advanced configuration.

What trigger types does Cloud Functions support?

HTTP triggers (a public or authenticated HTTPS endpoint), Pub/Sub triggers (function runs when a message is published to a topic), Cloud Storage triggers (file uploaded, deleted, or modified), Firestore events, Firebase events, and any event source supported by Eventarc including Cloud Audit Logs. HTTP triggers are most common for webhooks and simple APIs. Pub/Sub and Storage triggers are the standard patterns for event-driven pipelines.

What is a cold start in Cloud Functions?

A cold start happens when a request or event arrives and no warm function instance is available. GCP must start a new instance, which adds latency, typically a few hundred milliseconds to a couple of seconds depending on the runtime and how much your function loads on startup. Cloud Functions 2nd gen supports minimum instances to keep one instance warm at all times, eliminating cold starts at the cost of always paying for that instance.

Last verified: 22 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.