Functions
Functions are one of the Quave ONE app types. They are serverless-style applications on Quave ONE that automatically scale based on incoming traffic, including the ability to scale to zero when idle. They are powered by Knative and are ideal for event-driven workloads, APIs with variable traffic, webhooks, and background processors that don't need to run continuously.
How Functions Work
Unlike regular apps that maintain a fixed number of containers, functions dynamically adjust:
- Scale to zero: When no requests are received for a configurable idle period, the function scales down to zero containers, saving costs.
- Scale up on demand: When a request arrives, a container is started automatically (cold start). Subsequent requests are handled by active containers.
- Concurrency-based scaling: New containers are added when the number of concurrent requests per container exceeds the configured threshold.
Prerequisites
- The deployment region must support functions
If you want to run in a region where it's not available, please contact us.
Creating a Function App
Via the Web UI
- Navigate to Apps in your account
- Click Add function
- Choose the Use image deployment method
- Provide the Docker image URL for your function
- Select a region that supports functions
- Click Create
Via the API
curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "my-function",
"accountId": "YOUR_ACCOUNT_ID",
"port": 8080,
"dockerPreset": "FUNCTION",
"useImage": true,
"image": "docker.io/myorg/my-function:latest"
}' \
https://api.quave.cloud/api/public/v1/app
Via CLI (build from source)
Create the app in the web UI or API, then deploy code directly:
quaveone deploy --user-token <token> --env <env name> \
--dir ./my-function
Quave ONE builds the Docker image from your Dockerfile and deploys it as a Knative function.
Via MCP
Ask your AI agent:
"Create a function app called my-function on port 3000 with a Dockerfile for CLI deployment"
Or with a pre-built image:
"Create a function app called my-function on port 8080 using image docker.io/myorg/my-function:latest"
The create-app MCP tool supports dockerPreset: "FUNCTION" for creating function apps, with either isCliDeployment: true (build from source) or useImage: true (pre-built image).
Function Configuration
Each function environment has a functionConfig that controls scaling and timeout behavior. You can configure these settings via the web UI, API, CLI, or MCP.
Configuration Fields
| Field | Type | Description | Default |
|---|---|---|---|
containerConcurrency | Integer | Maximum number of concurrent requests per container instance. When exceeded, new containers are started. | Knative default |
timeoutSeconds | Integer | Maximum time in seconds a request can take before being terminated. | Knative default |
idleTimeoutSeconds | Integer | Minimum last-pod retention after the autoscaler decides to scale to zero. MCP accepts 300 or more; the account minimum defaults to 900. Requires the operator update below. | Account default |
responseStartTimeoutSeconds | Integer | Maximum time in seconds to wait for the first byte of a response. | Knative default |
minScale | Integer | Minimum number of container instances to keep running. Set to 0 to allow scale-to-zero. | 0 |
maxScale | Integer | Maximum number of container instances. Subject to account-level maximum. | Account default |
Updating via the API
Use the dedicated function config endpoint:
curl -X PATCH \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"appEnvId": "YOUR_APP_ENV_ID",
"containerConcurrency": 80,
"timeoutSeconds": 300,
"idleTimeoutSeconds": 900,
"minScale": 0,
"maxScale": 5,
"applyImmediately": true
}' \
https://api.quave.cloud/api/public/v1/app-env/function-config
You can also update function config through the general update endpoint (PUT /api/public/v1/app-env) by including a functionConfig object in the request body.
Updating via CLI
Pass function flags during deployment:
quaveone deploy --user-token <token> --env <env name> \
--fn-container-concurrency 80 \
--fn-timeout 300 \
--fn-idle-timeout 900 \
--fn-min-scale 0 \
--fn-max-scale 5
Updating via MCP
Ask your AI agent:
"Set the max scale to 5 and idle timeout to 900 seconds for my production function"
The update-function-config MCP tool handles all function configuration changes.
Deploying Functions
Functions support two deployment methods: building from source (recommended) or deploying a pre-built Docker image. Both methods support an environment-level startup command override.
Build from Source (CLI)
Deploy your code directly and let Quave ONE build the Docker image for you:
quaveone deploy --user-token <token> --env <env name> \
--dir ./my-function
You can combine code deployment with function config updates:
quaveone deploy --user-token <token> --env <env name> \
--dir ./my-function \
--fn-timeout 300 --fn-min-scale 0 --fn-max-scale 5
You can also override the function image's startup command without changing the build:
quaveone deploy --user-token <token> --env <env name> \
--dir ./my-function \
--command "bun run start:function"
Build from Source (MCP)
Use the code upload flow: request-deploy-storage-key to get an upload URL, upload your code archive, then notify-code-upload to trigger the build. Quave ONE builds the image and deploys it to Knative. The final tool can also receive startupConfig or clearStartupConfig.
Deploy a Pre-Built Image (CLI)
If you already have a Docker image, deploy it directly:
quaveone deploy --user-token <token> --env <env name> \
--image docker.io/myorg/my-function:v1.2.3
You can combine image deployment with function config updates:
quaveone deploy --user-token <token> --env <env name> \
--image docker.io/myorg/my-function:v1.2.3 \
--fn-timeout 300 --fn-min-scale 0 --fn-max-scale 5
The same pre-built image can use a different command in this function environment:
quaveone deploy --user-token <token> --env <env name> \
--image docker.io/myorg/my-function:v1.2.3 \
--command "bun run start:function"
Startup configuration is persistent for the environment and is separate from
Knative scaling and timeout settings. Use --clear-command to return to the
image defaults.
Deploy a Pre-Built Image (API)
Use the deploy-image endpoint:
curl -X POST \
-H 'Authorization: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"appEnvId": "YOUR_APP_ENV_ID",
"image": "docker.io/myorg/my-function:v1.2.3",
"startupConfig": {
"command": "bun run start:function",
"shell": true
}
}' \
https://api.quave.cloud/api/public/v1/app-env/deploy-image
Function apps can use the deploy-image endpoint without needing useImage=true on the app.
Deploy a Pre-Built Image (MCP)
Ask your AI agent:
"Deploy image docker.io/myorg/my-function:v1.2.3 to my production function and start it with bun run start:function"
Scaling Behavior
Cold Starts
When a function is scaled to zero and a request arrives, a new container must start before it can handle the request. This introduces a cold start delay. To minimize cold starts:
- Set
minScaleto 1 or higher to keep at least one container warm - Optimize your container startup time (keep the image small, minimize initialization work)
- Use
responseStartTimeoutSecondsto configure how long to wait for the first response byte
Scale-to-Zero
Knative autoscaling can reduce a Function to zero containers when idle, provided minScale is zero and scale-to-zero is enabled. On upgraded operators, idleTimeoutSeconds retains the final pod after the autoscaler decides to scale to zero; see the rollout prerequisite below.
- The MCP input minimum for
idleTimeoutSecondsis 300 seconds. The account'sfunctionMinIdleTimeoutSecondsdefaults to 900 seconds (15 minutes); lower submitted values are raised to that account minimum. For example, requesting 600 with the default account minimum stores 900, not 600. - Scale-to-zero can be disabled at the account level by setting
functionScaleToZerotofalse
Concurrency-Based Scaling
Knative monitors the number of concurrent requests per container. When the containerConcurrency limit is approached, new containers are started to handle the load, up to the maxScale limit.
Differences from Regular Apps
| Aspect | Regular Apps | Functions |
|---|---|---|
| Scaling | Fixed containers or HPA autoscaling | Knative concurrency-based, scale to zero |
| Domain | Standard app domain | Dedicated function domain |
| Billing | Standard per-container pricing | 3x multiplier on function pod time |
| Pods | Recent pods shown | Last 20 pods shown regardless of status |
| Regions | All enabled regions | Only regions with function domain support |
| Persistent Storage | Supported (volumes) | Not supported |
Billing
Function pods are billed at 3x the standard per-container rate. This multiplier accounts for the Knative infrastructure overhead and the scale-to-zero capability. When your function is scaled to zero, you are not billed for container time. See Pricing details for how this relates to the standard zCloud rate.
Observability
Functions support the same observability tools as regular apps:
- Logs: View function logs via the web UI, API (
GET /logs), CLI, or MCP (get-logs) - Requests: Open the Function environment's Requests tab in the web UI to inspect recent HTTP request volume, status codes, and latency from ingress access logs.
- Pods: View function pods via the web UI, API (
GET /app-env/pods), or MCP (get-app-env-pods). Functions show the last 20 pods regardless of termination status - History: View deployment history via the web UI, API (
GET /app-env/history), or MCP (get-app-env-history) - Status: Check function status via the web UI, API (
GET /app-env/status), or MCP (get-app-env-status)
Note: Traditional CPU and memory metrics are not collected for functions since containers are ephemeral.
Managing Functions via MCP
The following MCP tools are useful for managing functions:
| Tool | Description |
|---|---|
create-app | Create a function app with dockerPreset: "FUNCTION" (supports both isCliDeployment and useImage) |
update-function-config | Update function scaling and timeout settings |
request-deploy-storage-key | Get upload URL for code deployment (Step 1 of build from source) |
notify-code-upload | Trigger build after code upload and optionally update or clear startupConfig |
deploy-app-env-image | Deploy a pre-built Docker image and optionally update or clear startupConfig |
get-app-env | View function configuration (includes functionConfig and isFunction flag) |
get-app-env-status | Check function runtime status |
get-app-env-pods | View function pod details |
get-logs | View function logs |
stop-app-env | Stop a function environment |
start-app-env | Start a stopped function environment |
Limitations
Current migration and timeout limitations
Protected App-to-Function conversion requires the routing and timeout operator update tracked in infra issue #1015. Confirm that update is deployed in your target region before converting private content; staging qualification does not imply production availability.
On upgraded clusters, all published default and custom hostnames share the platform Basic Auth and TLS ingress. The Function backend is cluster-local, so the wildcard Function route cannot bypass authentication. Certificates are issued and renewed by cert-manager independently of Function pods, including while the Function is scaled to zero. Explicitly stopping an environment is different: it removes the public route and suspends its automatic certificate renewal.
App/Function type conversion through update-app preserves the existing image
or Dockerfile deployment source. It does not enable changing a Function's source
mode or bypass region/account restrictions. Persistent volumes, TCP, extra-port
paths, SockJS affinity, and custom ingress auth/snippet overrides are not
supported. Verify authentication on every public endpoint after conversion.
timeoutSeconds is the overall request deadline; the first-byte deadline is
bounded by that overall deadline. idleTimeoutSeconds controls Knative's
scale-to-zero pod retention:
the minimum time the last pod remains after the autoscaler decides to scale to
zero. It is not an exact timer from the last request, nor Knative's
response-byte idle timeout.
Older operators do not correctly enforce these settings.
Other limitations
- Dockerfile required: Functions must have a Dockerfile for building from source. Docker presets that auto-generate Dockerfiles are not supported for functions.
- No persistent volumes: Functions cannot use persistent storage (
useVolumeis not supported). - Region restrictions: Functions are only available in regions that have a function domain configured.
- No traditional autoscaling: Functions use Knative's concurrency-based scaling instead of the HPA autoscaling available for regular apps. The
update-app-env-scaling-optionsandscale-app-env-containerstools do not apply to functions. - Startup command support: Functions support the same shell, direct, args-only, working-directory, and reset behavior as regular Apps.