Configure runtime and secrets
Set a function's timeout and memory, allow-list outbound hosts, add config keys, and store credentials in secret bundles.
Set the runtime envelope your function executes in, open up the outbound network calls it needs, and give it credentials without putting them in your source. Everything here is per-function except secret bundles, which are shared across the tenant.
Before you begin
- The function already exists. If not, start with Create and build a function.
- You are an Admin working in the Global Organization.
- Have the exact hostnames of any API your handler calls. Wildcards are not accepted.
Runtime limits
Open the function and use the Settings tab. The first card bounds a single invocation.
| Setting | Range | Default | What it controls |
|---|---|---|---|
| Timeout (ms) | 50 – 2000 | 2000 | Wall-clock time your handler gets. Also the effective processing limit — a runaway loop is interrupted when the clock runs out. |
| Max memory pages | 1 – 64 | 32 | Memory available to your handler, at 64 KiB per page. The default is 2 MiB and the ceiling is 4 MiB. |
Leaving a field empty uses the service default. Because the default timeout is already the ceiling, the only useful direction to move it is down.
On a hook, a timeout is a refused signup — not a graceful degradation
A hook runs inside a real user's request, so a 2000 ms timeout can add two seconds to every signup the binding covers. Tightening it is tempting, but hooks fail closed: an expired handler is treated as a refusal, so a shorter timeout trades latency for lost customers.
Do the arithmetic before you change it. Your handler gets at most 2000 ms, and a single HTTP request inside it can take up to 1500 ms. Set the handler to 400 ms because your provider's median is 180 ms, and every slow response in the tail — a provider blip, a DNS hiccup, a TLS renegotiation — refuses a real signup.
Leave headroom for your dependency's slow tail, and catch its failures in code rather than letting them expire: a handler timeout cannot be caught, but an HTTP error can. See when your provider fails.
Beyond the timeout, two limits apply to every function and cannot be raised: a maximum of 20 SDK calls per invocation, and a 1500 ms timeout on each individual HTTP request.
Allowed hosts
The second card is the outbound network allow-list. This is the single most common reason a working handler fails in production.
- A function with no allowed hosts is refused every outbound request. This is the default for a new function.
- Entries are exact hostnames, matched case-insensitively —
api.example.com. Wildcards, paths, ports, and raw IP addresses are all rejected. - Only
httpandhttpsare permitted. - You can add up to 16 hosts. The card shows a live count.
Type a hostname and press Enter or select Add. Each host becomes a removable chip.
Private and internal addresses are always refused
Private network ranges, loopback, link-local addresses, and internal cluster hostnames are blocked even if you add them to the allow-list. The check is repeated after DNS resolution, so a public hostname that resolves to a private address is also refused. A blocked call raises an EGRESS_BLOCKED error in your handler.

Plugin config
The third card holds free-form key and value pairs that your handler reads at runtime with OmniLab.Config.get. Use it for things that differ between environments or organizations but are not sensitive — a template id, a feature toggle, a base URL.
const templateId = OmniLab.Config.get("brevo_template_id");You can store up to 32 keys, totalling 4 KB. Reading a key that is not set returns undefined. Rows with an empty key are discarded when you save.
Never put credentials in plugin config
Plugin config values are stored as plain configuration and are readable by anyone who can open the function. API keys, tokens, and passwords belong in a secret bundle.
Secret bundles
A secret bundle groups credentials under one key — for example a brevo bundle holding api_key. Bundles live at tenant level so several functions can share them, and values are write-only: once saved, they are never shown again.
Create a bundle
Scroll to the Secrets section below the function list on the Functions tab and select New secret.
| Field | What to enter |
|---|---|
| Key | The name you use in code. Lowercase letters, digits, and underscores, starting with a letter, up to 32 characters. Permanent. |
| Display name | A human-readable label, such as Brevo Production. |
| Description | Optional note about what the credentials are for. |
Then add one secret per credential, with a key such as API_KEY and its value. Select Save secrets.
A tenant can hold 5 bundles, each with up to 32 secrets.

Bind a bundle to a function
On the function's Settings tab, use the Secret bundles card and select the bundles this function should be able to read. A function can bind up to 5 bundles.
Once bound, the card lists a ready-to-copy reference for every secret in the bundle. Read a value at runtime with its fully qualified name:
const apiKey = OmniLab.Config.getSecret("brevo.api_key");A function can only read secrets from the bundles bound to it. Reading a key that does not exist throws a NOT_FOUND error rather than returning empty, so a typo fails loudly.
Change or remove a secret
Reopen the bundle. Existing values show a masked placeholder — leave a row untouched to keep its value, type a new value to replace it, or use the row's toggle to mark it for removal. A bundle cannot be deleted while a function still references it.
Save your changes
Select Save settings. Runtime limits, allowed hosts, plugin config, and bundle bindings all take effect on the next invocation — none of them require a rebuild, because none of them change your compiled code.
If something's blocked
An HTTP call fails with EGRESS_BLOCKED. The hostname is not in the allow-list, is spelled differently from what you allow-listed, uses a scheme other than HTTP or HTTPS, or resolves to a private address.
Reading a secret throws NOT_FOUND. Check that the bundle is bound to this function on the Settings tab, and that the reference is bundle_key.secret_key — both halves matter.
A bundle you bound shows as unknown. The bundle was deleted after it was bound. Remove the stale reference and bind an existing bundle.
Writing a contact custom field is rejected. Keys beginning system. or feature. are reserved by the platform. Choose a different key.
A timeout value is refused. The field accepts 50 to 2000 milliseconds. Values above the ceiling are not accepted, because the ceiling exists to keep synchronous hooks off the critical path for longer than that.