This document describes best practices for designing, implementing, testing, and deploying Cloud Run functions.
Correctness
This section describes general best practices for designing and implementing Cloud Run functions.
Write idempotent functions
Your functions should produce the same result even if they are called multiple times. This lets you retry an invocation if the previous invocation fails part way through your code. For more information, see retrying event-driven functions.
Ensure HTTP functions send an HTTP response
If your function is HTTP-triggered, remember to send an HTTP response, as shown below. Failing to do so can result in your function executing until timeout. If this occurs, you will be charged for the entire timeout time. Timeouts may also cause unpredictable behavior or cold starts on subsequent invocations, resulting in unpredictable behavior or additional latency.
Node.js
Python
Go
Java
C#
Ruby
PHP
Do not start background activities
Background activity is anything that happens after your function has terminated.
A function invocation finishes once the function returns or otherwise signals
completion, such as by calling the callback argument in Node.js event-driven
functions. Any code run after graceful termination cannot access the CPU and
will not make any progress.
In addition, when a subsequent invocation is executed in the same environment,
your background activity resumes, interfering with the new invocation. This may
lead to unexpected behavior and errors that are hard to diagnose. Accessing
the network after a function terminates usually leads to connections being reset
(ECONNRESET error code).
Background activity can often be detected in logs from individual invocations, by finding anything that is logged after the line saying that the invocation finished. Background activity can sometimes be buried deeper in the code, especially when asynchronous operations such as callbacks or timers are present. Review your code to make sure all asynchronous operations finish before you terminate the function.
Always delete temporary files
Local disk storage in the temporary directory is an in-memory filesystem. Files that you write consume memory available to your function, and sometimes persist between invocations. Failing to explicitly delete these files may eventually lead to an out-of-memory error and a subsequent cold start.
You can see the memory used by an individual function by selecting it in the list of functions in the Google Cloud console and choosing the Memory usage plot.
If you need access to long term storage, consider using Cloud Run volume mounts with Cloud Storage or NFS volumes.
You can reduce memory requirements when processing larger files using pipelining. For example, you can process a file on Cloud Storage by creating a read stream, passing it through a stream-based process, and writing the output stream directly to Cloud Storage.
Functions Framework
To ensure that the same dependencies are installed consistently across environments, we recommend that you include the Functions Framework library in your package manager and pin the dependency to a specific version of Functions Framework.
To do this, include your preferred version in the relevant lock file (for example,
package-lock.json for Node.js, or requirements.txt for Python).
If Functions Framework is not explicitly listed as a dependency, it will automatically be added during the build process using the latest available version.
Tools
This section provides guidelines on how to use tools to implement, test, and interact with Cloud Run functions.
Local development
Function deployment takes a bit of time, so it is often faster to test the code of your function locally.
Error reporting
In languages that use exception handling, do not throw uncaught exceptions, because they force cold starts in future invocations.
Do not manually exit
Manually exiting can cause unexpected behavior. Please use the following language-specific idioms instead:
Node.js
Do not use process.exit(). HTTP functions should send a response with
res.status(200).send(message), and event-driven
functions will exit once they return (either implicitly or explicitly).
Python
Do not use sys.exit(). HTTP functions should explicitly return
a response as a string, and event-driven functions will exit once
they return a value (either implicitly or explicitly).
Go
Do not use os.Exit(). HTTP functions should explicitly return
a response as a string, and event-driven functions will exit once
they return a value (either implicitly or explicitly).
Java
Do not use System.exit(). HTTP functions should send a response with
response.getWriter().write(message), and event-driven
functions will exit once they return (either implicitly or explicitly).
C#
Do not use System.Environment.Exit(). HTTP functions should send a response with
context.Response.WriteAsync(message), and event-driven
functions will exit once they return (either implicitly or explicitly).