Server Functions
Server functions are optional server-side logic that runs on the Lumio API. They let extensions persist structured data, query databases, call external APIs, and manage secrets — all in a sandboxed, isolated environment.
Enabling server functions
Add "server": true to lumio.config.json:
{
"server": true
}
This enables the server/ directory and activates the server runtime for your extension.
Two styles
| Style | Use case | Overhead |
|---|---|---|
| Declarative | Simple CRUD on tables (queryRows, insertRow, patchRow, deleteRow) | Minimal — transpiles to parameterized SQL, no JS runtime |
| Handler-based | Complex logic, external APIs, conditional writes (query(), mutation(), action()) | Low — runs in a V8 isolate with memory and CPU limits |
Execution flow
Extension Client (browser)
-> useMutation("addRule") / useQuery("getRules")
-> postMessage to Lumio host
-> Lumio API: POST /v1/extension-functions/{install_id}/{functionName}
-> Auth check + rate limit check
-> Declarative: parameterized SQL -> PostgreSQL (ext_{extension_id}.*)
-> Handler: V8 isolate -> ctx.db / ctx.fetch / ctx.secrets
-> Response serialized to JSON
-> postMessage back to extension
Rate limits
| Function type | Limit | Applies to |
|---|---|---|
queryRows | 100 calls/minute | Per installation |
insertRow / patchRow / deleteRow | 50 calls/minute | Per installation |
query() | 100 calls/minute | Per installation |
mutation() | 50 calls/minute | Per installation |
action() | 20 calls/minute | Per installation |
Database isolation
Each extension gets its own isolated PostgreSQL schema: ext_\{extension_id\}. Tables defined in server/schema.ts live in this schema:
ext_88b2478a_39c7_468e_bebd_14e52fd97ac0.rules
ext_88b2478a_39c7_468e_bebd_14e52fd97ac0.votes
No extension can read or write another extension's tables. The Lumio API enforces this at the query level.
File structure
server/
├── schema.ts <- Table definitions (defineSchema + defineTable)
└── functions.ts <- Function exports (queryRows, action, etc.)
Both files are optional. An extension can have server: true but only use schema for useExtensionStorage() type safety, without defining custom functions.
When to use server functions
| Scenario | Recommendation |
|---|---|
| Simple toggle / text setting | useExtensionStorage() — no server needed |
| List of items (rules, songs, votes) | Declarative server functions + defineTable |
| Aggregations (count, sum, averages) | Handler-based query() |
| External API calls (sports scores, weather) | Handler-based action() |
| User-specific data (per-viewer state) | Handler-based with ctx.auth.userId |
| Secrets (API keys) | Handler-based action() with ctx.secrets |