Skip to content

Serverless Functions

Zatabase includes a full serverless functions platform. Write a function in your language of choice, deploy it, and invoke it synchronously or asynchronously. Functions run in isolated Docker containers with configurable resource limits, warm-instance pooling for low-latency repeat calls, and built-in metrics. Triggers let you wire functions to cron schedules, database changes, storage events, message queues, and inbound webhooks without any external infrastructure.

RuntimeIdentifierBase ImageEntrypoint
Node.jsNodeJsnode:<version>-alpineindex.js
PythonPythonpython:<version>-alpinemain.py
RustRustrust:<version>-alpine (multi-stage)main.rs
GoGogolang:<version>-alpine (multi-stage)main.go
CustomCustomAny Docker image you specifyUser-defined

Rust and Go runtimes use multi-stage builds: the first stage compiles the binary, the second stage copies it into a minimal Alpine image.

Register a function with a name and runtime. This does not deploy any code yet — it creates the metadata record.

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "hello-world",
"description": "A simple greeting function",
"runtime": { "NodeJs": { "version": "18" } },
"tags": ["example", "getting-started"]
}' | jq

Response:

{
"function": {
"id": "a1b2c3d4-...",
"org_id": "org-123",
"name": "hello-world",
"description": "A simple greeting function",
"runtime": { "NodeJs": { "version": "18" } },
"current_deployment": null,
"tags": ["example", "getting-started"],
"enabled": true,
"created_at": "2026-03-04T12:00:00Z",
"updated_at": "2026-03-04T12:00:00Z"
}
}

Python 3.11:

{ "runtime": { "Python": { "version": "3.11" } } }

Rust (latest):

{ "runtime": { "Rust": { "version": "1.79" } } }

Go 1.21:

{ "runtime": { "Go": { "version": "1.21" } } }

Custom Docker image:

{ "runtime": { "Custom": { "image": "my-registry.io/my-runtime:latest" } } }

A deployment packages your code and configuration into a versioned, buildable unit. Create a deployment, build it, then activate it.

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/deployments \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"version": "1.0.0",
"code": {
"Inline": {
"source": "exports.handler = async (event) => { return { statusCode: 200, body: { message: \"Hello, \" + (event.body?.name || \"World\") + \"!\" } }; };"
}
},
"entrypoint": "index.js",
"environment": {
"LOG_LEVEL": "info"
},
"resource_limits": {
"memory_mb": 512,
"cpu_millicores": 1000,
"timeout_seconds": 30
}
}' | jq

Functions support three code source types:

Inline — embed source code directly in the request (best for small functions):

{
"code": {
"Inline": { "source": "exports.handler = async (event) => { ... };" }
}
}

Git — pull from a repository:

{
"code": {
"Git": {
"url": "https://github.com/your-org/your-function.git",
"branch": "main",
"commit": "abc123"
}
}
}

Archive — upload a tar.gz or zip:

{
"code": {
"Archive": {
"content": "<base64-encoded-bytes>",
"content_type": "application/gzip"
}
}
}

Building creates a Docker image from your code and runtime:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/deployments/$DEPLOYMENT_ID/build \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Response:

{
"message": "Deployment built successfully",
"image_tag": "zatabase/function:<function_id>_<deployment_id>",
"deployment_id": "..."
}

The deployment status transitions through: Pending -> Building -> Ready (or Failed).

Set this deployment as the active version for the function:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/deployments/$DEPLOYMENT_ID/activate \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Every deployment has configurable resource limits:

ParameterDefaultDescription
memory_mb512Maximum memory in megabytes
cpu_millicores1000CPU allocation (1000 = 1 core)
timeout_seconds30Maximum execution time
max_requests_per_secondunlimitedRate limit per function
max_concurrent_executions10Concurrency limit
max_payload_size_mb10Maximum request body size

Customize the build process with install and build commands:

{
"build_config": {
"install_commands": ["pip install -r requirements.txt"],
"build_commands": ["python -m compileall ."],
"ignore_patterns": [".git", "__pycache__", "*.pyc"],
"environment_variables": {
"PIP_NO_CACHE_DIR": "1"
}
}
}

Execute a function and wait for the result:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/execute \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": { "name": "Zatabase" },
"headers": { "x-custom": "value" },
"query": { "format": "json" }
}' | jq

Response:

{
"execution": {
"id": "exec-...",
"function_id": "...",
"deployment_id": "...",
"status": "Succeeded",
"started_at": "2026-03-04T12:01:00Z",
"completed_at": "2026-03-04T12:01:00.150Z",
"duration_ms": 150,
"memory_used_mb": 45,
"cold_start": false,
"response": {
"statusCode": 200,
"body": { "message": "Hello, Zatabase!" }
}
}
}

Fire-and-forget — returns an execution ID immediately:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/execute-async \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": { "data": [1, 2, 3, 4, 5] }
}' | jq

Response:

{
"execution_id": "exec-...",
"message": "Function execution scheduled"
}

Poll for the result using the execution ID:

Terminal window
curl -s https://your-project.zatabase.io/v1/executions/$EXECUTION_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
Pending -> Running -> Succeeded
-> Failed
-> Timeout
-> Canceled

Each execution record includes duration, memory usage, CPU time, cold start status, and the response or error details.

Functions can be called directly via HTTP at /fn/<function_name>/<path>. All standard HTTP methods are supported:

Terminal window
# GET request
curl -s https://your-project.zatabase.io/fn/my-api/users \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# POST request
curl -s -X POST https://your-project.zatabase.io/fn/my-api/users \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}' | jq
# PUT request
curl -s -X PUT https://your-project.zatabase.io/fn/my-api/users/123 \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Alice Updated"}' | jq
# DELETE request
curl -s -X DELETE https://your-project.zatabase.io/fn/my-api/users/123 \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

The path after the function name is passed to your handler as the request path. Your function receives the full HTTP context including headers, query parameters, and body.

Triggers automatically invoke functions in response to events. Each function can have multiple triggers.

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/triggers \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trigger_type": "Schedule",
"config": { ... },
"enabled": true
}' | jq

Execute a function on a recurring schedule using standard cron syntax:

{
"trigger_type": "Schedule",
"config": {
"Schedule": {
"cron": "0 0 * * * *",
"timezone": "America/New_York"
}
}
}

The cron expression uses the 6-field format: second minute hour day-of-month month day-of-week. The scheduler checks for due jobs every 10 seconds. Timezone defaults to UTC if not specified or if the provided timezone is invalid.

Examples:

Cron ExpressionDescription
0 0 * * * *Every hour
0 */15 * * * *Every 15 minutes
0 0 9 * * 1-5Weekdays at 9 AM
0 0 0 1 * *First of every month at midnight

React to document and collection changes:

{
"trigger_type": "Database",
"config": {
"Database": {
"collection": "users",
"events": ["DocumentCreated", "DocumentUpdated"],
"filters": { "status": "active" }
}
}
}

Supported database events:

EventFires When
DocumentCreatedA new document is inserted
DocumentUpdatedAn existing document is modified
DocumentDeletedA document is removed
CollectionCreatedA new collection is created
CollectionDeletedA collection is dropped
IndexCreatedA new index is created
IndexUpdatedAn index is modified

The optional filters field applies simple key-value matching against the document. Only matching documents trigger execution.

React to file and bucket changes:

{
"trigger_type": "Storage",
"config": {
"Storage": {
"bucket": "uploads",
"events": ["FileCreated", "FileUpdated"],
"patterns": ["images/*", "documents/*.pdf"]
}
}
}

Supported storage events: FileCreated, FileUpdated, FileDeleted, BucketCreated, BucketDeleted.

The patterns field supports glob-like prefix matching. An empty patterns array matches all files in the bucket.

Process messages from a topic, with optional batching:

{
"trigger_type": "Queue",
"config": {
"Queue": {
"topic": "order-events",
"batch_size": 10
}
}
}

When batch_size is set, messages are grouped into batches before invoking the function. Without batch_size, each message triggers a separate invocation.

Receive inbound webhooks with optional signature verification:

{
"trigger_type": "Webhook",
"config": {
"Webhook": {
"secret": "whsec_your_secret_key",
"headers": {
"x-source": "github"
}
}
}
}

When a secret is configured, incoming requests must include an x-webhook-signature header with a valid SHA-256 HMAC signature. The headers field enforces that specific headers and values are present on the incoming request.

Terminal window
# List triggers for a function
curl -s https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/triggers \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Get a specific trigger
curl -s https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/triggers/$TRIGGER_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Update a trigger
curl -s -X PUT https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/triggers/$TRIGGER_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trigger_type": "Schedule",
"config": { "Schedule": { "cron": "0 */30 * * * *" } },
"enabled": true
}' | jq
# Delete a trigger
curl -s -X DELETE https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/triggers/$TRIGGER_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN"

Zatabase ships with built-in function templates so you can bootstrap common patterns without writing boilerplate. Templates use Handlebars syntax for variable substitution.

Terminal window
# List all templates
curl -s https://your-project.zatabase.io/v1/templates \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Filter by category
curl -s "https://your-project.zatabase.io/v1/templates?category=HttpApi" \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Search templates
curl -s "https://your-project.zatabase.io/v1/templates/search?search=webhook" \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# List available categories
curl -s https://your-project.zatabase.io/v1/templates/categories \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

API and Web: HttpApi, RestApi, GraphQl, Webhook. Data Processing: DataTransformation, Analytics, MachineLearning, ImageProcessing. Integrations: Database, Storage, Messaging, Email, Payment, Authentication. Utilities: Scheduled, Monitoring, DevOps, Testing. Industry: Ecommerce, Finance, Healthcare, IoT.

TemplateRuntimeCategoryDescription
Hello WorldNode.js 18TestingSimple starter function
HTTP API HandlerNode.js 18HttpApiRESTful endpoint with method routing
Webhook HandlerNode.js 18WebhookSecure webhook receiver with signature validation
Data ProcessorPython 3.11DataTransformationData transformation pipeline with validation
Email SenderNode.js 18EmailSMTP email sending with template support
Image ResizerPython 3.11ImageProcessingOn-demand image resize and optimization
Scheduled CleanupPython 3.11ScheduledAutomated cleanup for scheduled execution
Database TriggerNode.js 18DatabaseReact to database changes with custom logic
Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/templates/$TEMPLATE_ID/create \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"org_id": "org-123",
"function_name": "my-api-handler",
"variables": {
"resource_name": "users",
"required_field": "email"
}
}' | jq

This creates both the function and an initial deployment with version 1.0.0, populated from the template code with your variables substituted in.

Get aggregated metrics for a function:

Terminal window
curl -s https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/metrics \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Response:

{
"function_id": "...",
"invocation_count": 1523,
"average_duration_ms": 87,
"error_count": 12,
"success_rate": 0.992,
"last_invoked_at": "2026-03-04T11:59:00Z"
}

List recent executions for a function:

Terminal window
curl -s "https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/executions?limit=20" \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Each execution record includes:

  • duration_ms — total wall-clock time
  • memory_used_mb — memory consumed during execution
  • cpu_time_ms — CPU time used
  • cold_start — whether a new container was created
  • cold_start_duration_ms — container startup time (if cold start)
  • response — the function’s return value
  • error — error details if the execution failed

Get overall platform health and execution statistics:

Terminal window
curl -s https://your-project.zatabase.io/v1/platform/stats \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
curl -s https://your-project.zatabase.io/v1/platform/health \
-H "Authorization: Bearer $ZATABASE_TOKEN"
Terminal window
curl -s https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/deployments \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

If a deployment is problematic, roll back to a known-good version:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/functions/$FUNCTION_ID/rollback \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "version": "1.0.0" }' | jq

This finds the deployment matching the specified version and activates it.

Terminal window
curl -s "https://your-project.zatabase.io/v1/functions?offset=0&limit=50" \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
Terminal window
curl -s -X PUT https://your-project.zatabase.io/v1/functions/$FUNCTION_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "hello-world-v2",
"description": "Updated greeting function",
"enabled": true,
"tags": ["production", "api"]
}' | jq
Terminal window
curl -s -X DELETE https://your-project.zatabase.io/v1/functions/$FUNCTION_ID \
-H "Authorization: Bearer $ZATABASE_TOKEN"

Returns 204 No Content on success.

Functions execute in Docker containers. The platform maintains a pool of warm instances to avoid cold-start latency on repeat calls.

  • Cold start: A new container is created and started. Typical cold-start overhead is container pull + initialization time (reported in cold_start_duration_ms).
  • Warm start: An existing container is reused. The platform pools up to 3 warm instances per runtime by default, with a 5-minute idle timeout.

After execution, containers are returned to the warm pool. Idle containers are cleaned up automatically when the idle timeout expires.

Function operations are gated by Zatabase’s RBAC permission system. The following CRUD operations are enforced:

OperationRequired Permission
Create a functionCREATE on Jobs resource
List / get functionsREAD on Jobs resource
Update a functionUPDATE on Jobs resource
Delete a functionDELETE on Jobs resource
Execute a functionCREATE on Jobs resource
Activate / rollbackUPDATE on Jobs resource

Functions are scoped to the authenticated user’s organization. Attempting to access a function belonging to a different organization returns a 403 Forbidden error.

MethodEndpointDescription
POST/v1/functionsCreate a function
GET/v1/functionsList functions
GET/v1/functions/:idGet a function
PUT/v1/functions/:idUpdate a function
DELETE/v1/functions/:idDelete a function
POST/v1/functions/:id/deploymentsCreate a deployment
GET/v1/functions/:id/deploymentsList deployments
GET/v1/functions/:id/deployments/:versionGet a deployment
POST/v1/functions/:id/deployments/:did/buildBuild a deployment
POST/v1/functions/:id/deployments/:did/activateActivate a deployment
POST/v1/functions/:id/rollbackRollback to a version
POST/v1/functions/:id/executeExecute synchronously
POST/v1/functions/:id/execute-asyncExecute asynchronously
GET/v1/functions/:id/executionsList executions
GET/v1/executions/:idGet an execution
GET/v1/functions/:id/metricsGet function metrics
POST/v1/functions/:id/triggersCreate a trigger
GET/v1/functions/:id/triggersList triggers
GET/v1/functions/:id/triggers/:tidGet a trigger
PUT/v1/functions/:id/triggers/:tidUpdate a trigger
DELETE/v1/functions/:id/triggers/:tidDelete a trigger
GET/v1/templatesList templates
GET/v1/templates/:idGet a template
POST/v1/templates/:id/createCreate function from template
GET/v1/templates/categoriesList template categories
GET/v1/templates/searchSearch templates
GET/POST/PUT/DELETE/fn/:name/*pathHTTP function routing
GET/v1/platform/statsPlatform statistics
GET/v1/platform/healthHealth check
  • Functions execute inside Docker containers. Docker must be available on the host (the platform connects via the default Docker socket).
  • The maximum default execution timeout is 30 seconds. This can be increased per-deployment via resource_limits.timeout_seconds.
  • Archive code sources are packaged as-is into the build context. Large archives increase build time.
  • Git code sources require git to be installed on the host for cloning.
  • Warm instance pools have a default maximum of 3 instances per runtime and a 300-second idle timeout. These values are not yet configurable via the API.
  • Webhook signature validation uses SHA-256 hashing. HMAC-SHA256 is recommended for production workloads.
  • The container filesystem is read-only. Functions should write temporary files to /tmp (a 100 MB tmpfs mount).