Migrating Runtime Configurations (runWith)
In Cloud Functions for Firebase V1 (firebase-functions/v1), you configured
runtime settings like memory, timeout, and service accounts using .runWith().
In V2 (firebase-functions/v2), .runWith() is removed and replaced by a more
flexible options system.
You can configure V2 functions in two ways: Per-Function (passing an options
object directly to the trigger) or Globally (setGlobalOptions at the top
of a file).
1. Per-Function Configuration
Pass the configuration options object as the first argument to the V2 trigger function. Per-function options always override any global defaults.
V1 Legacy
import * as functions from "firebase-functions";
export const processOrder = functions
.runWith({ memory: "2GB" })
.pubsub.topic("orders")
.onPublish((message, context) => { ... });V2 Modern Equivalent
import { onMessagePublished } from "firebase-functions/v2/pubsub";
export const processOrder = onMessagePublished(
{
topic: "orders",
memory: "2GiB", // Options passed as the first argument!
},
({ message, context }) => { ... } // Destructuring shim pattern
);[!TIP] Memory Unit Caveat: V1 accepted
"1GB". V2 types strongly prefer IEC units like"1GiB","2GiB", etc.
2. Global Configuration (setGlobalOptions)
Use setGlobalOptions at the top of your file when all or most functions in
that file share the exact same runtime requirements (e.g. identical region,
memory allocation, timeout, or service account). Individual functions can still
override specific settings by declaring per-function options.
V1 Legacy
import * as functions from "firebase-functions";
export const myFn = functions
.runWith({
memory: "1GB",
timeoutSeconds: 120,
serviceAccount: "custom-sa@my-project.iam.gserviceaccount.com",
})
.https.onRequest((req, res) => { ... });V2 Modern Equivalent
import { setGlobalOptions } from "firebase-functions/v2";
import { onRequest } from "firebase-functions/v2/https";
// Set global defaults for all functions defined after this call in this file
setGlobalOptions({
memory: "1GiB", // Note: GiB instead of GB is preferred in V2 types
timeoutSeconds: 120,
serviceAccount: "custom-sa@my-project.iam.gserviceaccount.com",
});
export const myFn = onRequest((req, res) => { ... });Common Property Translations
| V1 Property | V2 Property | Notes |
|---|---|---|
memory |
memory |
Use "1GiB" instead of "1GB". |
timeoutSeconds |
timeoutSeconds |
Same. |
ingressSettings |
ingressSettings |
Same. |
vpcConnector |
vpcConnector |
Same. |
vpcConnectorEgressSettings |
vpcConnectorEgressSettings |
Same. |
serviceAccount |
serviceAccount |
Same. |
secrets |
secrets |
Same. |
failurePolicy |
retry |
Renamed to boolean retry: true/false in V2 Eventarc triggers. |
3. Migrating Environment Configurations (functions.config())
In V1, you used functions.config() to access environment configuration. In V2,
this is replaced by Parameterized Configuration.
Deterministic Rules for Migration
Follow these rules to ensure a deterministic and safe migration:
Typing & Exports
- Numbers: If the value is used as a number, use
defineIntordefineNumber. - Secrets: If the key contains "KEY", "SECRET", "TOKEN", or "PASSWORD", use
defineSecret()ordefineJsonSecret().- Note: Secrets MUST be explicitly bound to the function that uses them in
the options object (e.g.,
{ secrets: [myKey, myJsonSecret] }). BothSecretParamandJsonSecretParamare supported in thesecretsarray.
- Note: Secrets MUST be explicitly bound to the function that uses them in
the options object (e.g.,
- Lists: Use
defineListfor comma-separated lists. - JSON: Use
defineJSONfor JSON strings. - Buckets: If the param is a storage bucket, set
input: { text: {} }or bucket selector. - Input Validation: Use
nonEmpty: trueinsideinput.textorinput.multiSelectto enforce non-empty parameter input during CLI prompting (e.g.defineString("PARAM", { input: { text: { nonEmpty: true } } })). - Type Annotations: Import parameter types directly from
firebase-functions/params(e.g.import type { StringParam, SecretParam, JsonSecretParam, IntParam } from "firebase-functions/params").
Initialization & Scope
- Global Initialization: If a variable was initialized globally in V1 (e.g.,
const client = new Client(functions.config().key)), you must split it to have declaration at global scope and initialization insideonInit:import { onInit } from "firebase-functions/v2"; const myKey = defineSecret("MY_KEY"); let client: Client; onInit(() => { client = new Client(myKey.value()); });
Advanced Interpolation & Logic
- String Interpolation: Use the
exprtagged template literal fromfirebase-functions/params(e.g.,`expr`every ${period} days`) instead of standard template literals when constructing dynamic strings with parameters. Do NOT call.value()insideexpr. - Logic Operators: Use expressions like
projectID.equals('prod').thenElse(1, 0)for logical operations instead of ternary operators on.value().
Built-ins
- Prefer built-in variables like
databaseURL,projectID,gcloudProject,storageBucketrather than defining new params for these values.