Cloud Run functions execution environment
Cloud Run functions run in a fully-managed serverless environment where Google handles infrastructure, operating systems, and runtime environments. Each function runs in its own isolated secure execution context, scales automatically, and has a lifecycle independent from other functions.
Runtimes
Cloud Run functions supports multiple language runtimes. Each contains a standard set of system packages, as well as the tools and libraries needed for that language. You'll need the Runtime ID value if you're deploying functions from the command line or through Terraform.
Security and maintenance updates are made available to all Cloud Run functions and Cloud Run functions (1st gen) execution environments. These updates are applied automatically or manually, depending on the environment and how you've configured it. For more information about execution environment updates, see Secure your Cloud Run function.
Runtime images are hosted in every region where Artifact Registry is available. You can customize the runtime image path by replacing the first portion of the URI with your region of choice:
REGION-docker.pkg.dev/serverless-runtimes/STACK/runtimes/RUNTIME_ID
Replace:
- REGION with the preferred region, for example
us-central1
- STACK with the preferred operating system stack, for example
google-22-full
- RUNTIME_ID with the runtime ID used by your function, for example
python310
For example, the latest Node.js 20 base image using the google-22-full
stack,
hosted in us-central1
would be referenced with this URL:
us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
Node.js 22 (preview only) |
nodejs22 |
|
|
Node.js 20 | nodejs20 |
|
|
Node.js 18 | nodejs18 |
|
|
Node.js 16 | nodejs16 | google-18-full | google-18-full/nodjes16 |
Node.js 14 | nodejs14 | google-18-full | google-18-full/nodjes14 |
Node.js 12 | nodejs12 | google-18-full | google-18-full/nodjes14 |
Node.js 10 | nodejs10 | google-18-full | google-18-full/nodjes10 |
Node.js 8 | nodejs8 | Decommissioned | Decommissioned |
Node.js 6 | nodejs6 | Decommissioned | Decommissioned |
Python
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
Python 3.12 | python312 |
|
|
Python 3.11 | python311 |
|
|
Python 3.10 | python310 |
|
|
Python 3.9 | python39 | google-18-full | google-18-full/python39 |
Python 3.8 | python38 | google-18-full | google-18-full/python38 |
Python 3.7 | python37 | google-18-full | google-18-full/python37 |
Go
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
Go 1.22 | go122 |
|
|
Go 1.21 | go121 |
|
|
Go 1.20 | go120 |
|
|
Go 1.19 | go119 |
|
|
Go 1.18 | go118 |
|
|
Go 1.16 | go116 | google-18-full | google-18-full/go116 |
Go 1.13 | go113 | google-18-full | google-18-full/go113 |
Go 1.11 | go111 | Decommissioned | Decommissioned |
Java
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
Java 21 | java21 |
|
|
Java 17 | java17 |
|
|
Java 11 | java11 | google-18 | google-18/java11 |
Ruby
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
Ruby 3.3 | ruby33 |
|
|
Ruby 3.2 | ruby32 |
|
|
Ruby 3.0 | ruby30 | google-18-full | google-18-full/ruby30 |
Ruby 2.7 | ruby27 | google-18-full | google-18-full/ruby27 |
Ruby 2.6 | ruby26 | google-18-full | google-18-full/ruby26 |
PHP
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
PHP 8.3 | php83 |
|
|
PHP 8.2 | php82 |
|
|
PHP 8.1 | php81 | google-18-full | google-18-full/php81 |
PHP 7.4 | php74 | google-18-full | google-18-full/php74 |
.NET Core
Runtime | Runtime ID | Stacks | Runtime base image |
---|---|---|---|
.NET Core 8 | dotnet8 |
|
|
.NET Core 6 | dotnet6 |
|
|
.NET Core 3 | dotnet3 | google-18-full | google-18-full/dotnet3 |
Auto-scaling behavior
Cloud Run functions implements the serverless paradigm, in which you run your code without worrying about the underlying infrastructure, such as servers or virtual machines. Once deployed, your functions are automatically managed and scaled.
Cloud Run functions handles incoming requests by assigning them to instances of your function. Depending on the volume of requests, as well as the number of existing function instances, Cloud Run functions may assign a request to an existing instance or create a new one.
In cases where inbound request volume exceeds the number of existing instances, Cloud Run functions may start multiple new instances to handle requests. This automatic scaling behavior allows Cloud Run functions to handle many requests in parallel, each using a different instance of your function.
In some cases, unbounded scaling might be undesirable. To address this, Cloud Run functions allows you to configure a maximum number of instances that can coexist at any given time for a particular function.
Statelessness
To enable automatic management and scaling of your functions, functions must be stateless—one function invocation must not rely on in-memory state set by a previous invocation. Invocations might be handled by different function instances, which do not share global variables, memory, file systems, or other state.
If you need to share state across function invocations, your function should use a service such as Memorystore, Datastore, Firestore, or Cloud Storage to persist data. See Google Cloud databases and Google Cloud storage products for more information about database and storage options provided by Google Cloud.
Concurrency
Cloud Run functions
Cloud Run functions supports handling multiple concurrent requests on a single function instance. This can be helpful in preventing cold starts since an already warmed instance can process multiple requests simultaneously, thereby reducing overall latency. For details, see Concurrency.
Cloud Run functions (1st gen)
In Cloud Run functions (1st gen), each instance of a function handles only one concurrent request at a time. This means that while your code is processing one request, there is no possibility of a second request being routed to the same instance. Thus the original request can use the full amount of resources (memory and CPU) that you allocate.
Because concurrent requests in Cloud Run functions (1st gen) are processed by different function instances, they do not share variables or local memory. See Statelessness and Function instance lifespan for more information.
Cold starts
A new function instance is started in two cases:
When you deploy your function.
When a new function instance is automatically created to scale up to the load, or occasionally to replace an existing instance.
Starting a new function instance involves loading the runtime and your code. Requests that include function instance startup, called cold starts, can be slower than requests routed to existing function instances. If your function receives steady load, however, then the number of cold starts is typically negligible unless your function frequently crashes and requires restarting of the function environment.
If your function code throws an uncaught exception or crashes the current process, the function instance might be restarted. This can lead to more cold starts, resulting in higher latency, so we recommend catching exceptions and otherwise avoiding termination of the current process. See Reporting errors for a discussion of how to handle and report errors in Cloud Run functions.
If your function is latency-sensitive, consider setting a minimum number of instances to avoid cold starts.
Function instance lifespan
Function instances are typically resilient and reused by subsequent function invocations, unless the number of instances is being scaled down due to lack of ongoing traffic or your function crashes. This means that when one function execution ends, another function invocation can be handled by the same function instance.
Function scope versus global scope
A single function invocation results in execution of only the body of the function declared as the entry point. The global scope of your function source code is only executed on cold starts, and not on instances that have already been initialized.
Node.js
Python
Go
Java
Ruby
You can use global variables as a performance optimization, but you must not rely on state set in the global scope by previous function invocations - see Statelessness for more information.
You can assume that for each function instance, the global scope has been executed exactly once before your function code is invoked. However, you must not depend on the total number of or timing of global scope executions, as they might vary depending on auto-scaling activity.
Function execution timeline
A function has access to its allocated resources (memory and CPU) only for the duration of function execution. Code run outside of the execution period is not guaranteed to execute, and it can be stopped at any time. Therefore, you should always signal the end of your function execution correctly and avoid running any code beyond it. See HTTP Functions, Background Functions, and CloudEvent Functions for guidance.
Function execution is also subject to the timeout duration of the function. See Function timeout for more information.
Take into account the execution timeline when initializing your application. Background tasks should not be created in global scope during initialization, as they would execute outside of the duration of a request.
Execution guarantees
Your functions are typically invoked once for each incoming event. However, Cloud Run functions does not guarantee a single invocation in all cases because of differences in error scenarios.
The maximum or minimum number of times your function could be invoked for a single event depends on the type of your function:
HTTP functions are invoked at most once. This is because of the synchronous nature of HTTP calls, and it means that any error that occurs during function invocation will be returned without retrying. The caller of an HTTP function is expected to handle errors and retry if needed.
Event-driven functions are invoked at least once. This is because of the asynchronous nature of events, in which there is no caller that waits for the response. The system might, in rare circumstances, invoke an event-driven function more than once in order to ensure delivery of the event. If an event-driven function invocation fails with an error, the function won't be invoked again unless retries on failure are enabled for that function.
To make sure that your function behaves correctly on retried execution attempts, you should make it idempotent by implementing it so that the desired results (and side effects) are produced even if an event is delivered multiple times. In the case of HTTP functions, this also means returning the desired value even if the caller retries calls to the HTTP function endpoint. See Retrying Event-Driven Functions for more information on how to make your function idempotent.
Memory and file system
Each function has a certain amount of memory allocated for its use. You can configure the amount of memory at deployment - see Memory limits for more information.
The function execution environment includes an in-memory file system that contains the source files and directories deployed with your function (see Structuring source code). The directory containing your source files is read-only, but the rest of the file system is writeable (except for files used by the operating system). Use of the file system counts towards a function's memory usage.
Your function can interact with the file system using standard methods in each programming language.
Network
Your function can access the public internet using standard methods in each programming language, whether through built-in libraries offered by the runtime or third-party libraries you include as dependencies.
Try to reuse network connections across function invocations, as described in Optimizing Networking. However, note that a connection that remains unused for 10 minutes might be closed by the system, and further attempts to use a closed connection will result in a "connection reset" error. Your code should either use a library that handles closed connections well, or handle them explicitly if using low-level networking constructs.
Function isolation
Every deployed function is isolated from all other functions—even those deployed from the same source file. In particular, they do not share memory, global variables, file systems, or other state.
To share data across deployed functions, you can use services such as Memorystore, Datastore, Firestore, or Cloud Storage. Alternatively, you can invoke one function from another using their appropriate triggers and passing along the necessary data. For example, make an HTTP request to the endpoint of an HTTP function or publish a message to a Pub/Sub topic to trigger a Pub/Sub function.