Skip to content
Discord Get Started

Configuration

Secrets let you pass sensitive values (API keys, tokens, connection strings) to functions without embedding them in code.

Terminal
# From stdin (recommended for CI/CD)
echo -n "sk-abc123" | db9 functions secrets set MY_API_KEY --db myapp --value-stdin
# Inline (visible in shell history — not recommended)
db9 functions secrets set MY_API_KEY --db myapp --value "sk-abc123"

The --secret flag maps an alias (used in your code) to a secret name (stored in the database):

Terminal
db9 functions create my-func --db myapp -f index.js \
--secret API_KEY=MY_API_KEY \
--secret DB_TOKEN=external_db_token
JavaScript
module.exports = {
handler: async (input, ctx) => {
const apiKey = ctx.secrets.get("API_KEY");
const response = await fetch("https://api.example.com/data", {
headers: { "Authorization": `Bearer ${apiKey}` },
});
return await response.json();
}
};
Terminal
# List secrets (names only — values are never shown)
db9 functions secrets list --db myapp
# Update (set uses create-or-update semantics)
db9 functions secrets set MY_API_KEY --db myapp --value "new-value"
# Delete
db9 functions secrets delete MY_API_KEY --db myapp

Functions can read and write files in the database’s filesystem. Access is controlled by --fs9-scope flags at deploy time:

Terminal
db9 functions create my-func --db myapp -f index.js \
--fs9-scope /data:ro \
--fs9-scope /output:rw
ModeDescription
roRead-only access to the path and its children
rwRead-write access to the path and its children

The --fs9-scope flags declare which paths your function intends to access and whether access is read-only or read-write. Currently, ctx.fs9 calls succeed even without --fs9-scope, but you should always declare scopes explicitly — enforcement may be enabled in a future release.

JavaScript
// Read as UTF-8 string
const text = await ctx.fs9.read("/data/config.json");
const config = JSON.parse(text);
// Read as base64 (for binary files like images, xlsx)
const base64 = await ctx.fs9.readBase64("/data/image.png");
const buffer = Buffer.from(base64, "base64");
JavaScript
await ctx.fs9.write("/output/report.csv", csvContent);
await ctx.fs9.write("/output/data.json", JSON.stringify(results, null, 2));
JavaScript
const entries = await ctx.fs9.list("/data/");
// Returns: [{ path, type, size, mtime, ... }, ...]
const stat = await ctx.fs9.stat("/data/file.txt");
// Returns: { path, type: "file", size: 1024, mtime: "2026-04-01T...",
// generation: 1, mode: 420, sealed: false, storage: "inline" }
JavaScript
await ctx.fs9.delete("/output/old-report.csv");

Functions have access to the global fetch() API for outbound HTTP requests. Network access is blocked by default — only URLs on the allowlist can be reached.

JavaScript
module.exports = {
handler: async (input, ctx) => {
const response = await fetch("https://api.example.com/data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: input.query }),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}
};

If a URL is not in the allowlist, fetch() throws with:

Output
EACCES: permission denied, connect 'https://...': url not in allowlist

Functions can be invoked on a schedule using pg_cron. This is useful for periodic data cleanup, report generation, and automated maintenance.

Use cron.schedule() to invoke a function on a recurring schedule:

SQL
SELECT cron.schedule(
'nightly-cleanup',
'0 3 * * *',
$$SELECT extensions.http_post(
'https://api.db9.ai/customer/databases/{db_id}/functions/{function_id}/invoke',
'{"input": {}}',
'application/json',
ARRAY[ARRAY['Authorization', 'Bearer ' || current_setting('app.api_token')]]
)$$
);
ExpressionMeaning
*/5 * * * *Every 5 minutes
0 * * * *Every hour
0 3 * * *Daily at 3:00 AM UTC
0 0 * * 0Weekly on Sunday at midnight
0 12 1 * *Monthly on the 1st at noon

See Scheduled Jobs with pg_cron for the complete scheduling guide.

Every db9 functions update creates a new version. The active version is updated immediately — there is no staged deployment.

Terminal
# Deploy version 1
db9 functions create my-func --db myapp -f v1.js
# Deploy version 2 (replaces version 1 immediately)
db9 functions update my-func --db myapp -f v2.js

Each run record stores the version_id that was used, so you can trace which version produced a given result:

Terminal
db9 functions history my-func --db myapp -n 5 --json

There is currently no built-in rollback command. To revert, re-deploy the previous version’s code:

Terminal
db9 functions update my-func --db myapp -f previous-version.js
LimitDefaultMaxDescription
timeout_ms30,000 (30s)300,000 (5 min)Maximum execution time
memory_mbSystem defaultMemory limit
max_db_queriesSystem defaultSQL queries per invocation
max_db_rowsSystem defaultTotal rows returned across queries
max_outbound_requestsSystem defaultOutbound HTTP requests
max_response_bytesSystem defaultMax size per HTTP response
network_timeout_msSystem defaultPer-request network timeout
max_fs9_requestsSystem defaultfs9 API calls per invocation
max_fs9_read_bytesSystem defaultTotal bytes read from fs9
max_fs9_write_bytesSystem defaultTotal bytes written to fs9

Set limits via flags or JSON:

Terminal
# Convenience flag (timeout only)
db9 functions create my-func --db myapp -f index.js --timeout 60000
# Full limits JSON
db9 functions create my-func --db myapp -f index.js \
--limits-json '{"timeout_ms":60000,"memory_mb":256,"max_db_queries":100}'
# From file
db9 functions create my-func --db myapp -f index.js \
--limits-file ./limits.json

Functions have a visibility field that defaults to private. This controls whether the function can be invoked via a publishable key (public endpoint) without authentication.