SlimFaas Functions (Sync & Async)
SlimFaas offers two main ways to invoke functions: synchronous and asynchronous HTTP calls. Below is an overview of each.
1. Synchronous Functions
Synchronous calls block until the underlying function pod handles the request and returns a response.
-
Route:
GET/POST/PUT/... http://<slimfaas>/function/<functionName>/<path> -
Example: GET http://localhost:30021/function/fibonacci1/hello/guillaume → 200 (OK) with response from fibonacci1
If your function has scaled to zero, SlimFaas automatically wakes it up and waits until at least one replica is ready (subject to internal timeouts).
2. Asynchronous Functions
Asynchronous calls return immediately (HTTP 202 or 201), while SlimFaas queues the request and processes it in the background.
202 Accepted is returned only after the queue mutation is durably committed.
FIFO order, retries, and callback behavior are unchanged. For request bodies
larger than 1 MiB, SlimFaas durably commits and validates the offload metadata
before it enqueues the message that refers to that body.
-
Route:
GET/POST/PUT/... http://<slimfaas>/async-function/<functionName>/<path> -
Example: GET http://localhost:30021/async-function/fibonacci1/hello/guillaume → 202 (Accepted), handled in background synchronous mode also allows:
-
Limiting parallel requests via annotations (e.g.,
SlimFaas/NumberParallelRequest). -
Retry pattern on timeouts or specific HTTP status codes.
Queue mutations wake the HTTP and WebSocket dispatch workers immediately after
their durable commit. Workers:QueuesDelayMilliseconds is therefore a maximum
fallback interval for a lost signal, a leadership transition, or a retry that
becomes eligible; it is no longer the normal queue polling latency. The local
SlimData wait for queue-critical mutations is controlled by
SlimData:QueueLowLatencyEnabled (default true) and
SlimData:QueueMutationMaxWaitMilliseconds (default 5, range 0–225).
Bodies stored through the internal offload path are prepared concurrently with a bounded parallelism, then dispatched in their original FIFO order. After a non-retryable result has been durably committed to the queue, SlimFaas removes its local file through a dedicated cleanup mailbox. This cleanup never blocks dispatch of the next message and broadcasts a best-effort delete signal for remote copies. Older or temporarily unavailable replicas fall back to the existing convergent orphan cleaner. Raft metadata deletion stays outside the dispatch mailbox and is grouped by the cleaner, so cleanup mutations cannot delay every new queue write. A retryable status keeps every artifact available for the next attempt.
3. Wake Function
You can explicitly “wake up” a function without invoking a specific route:
-
Route:
GET http://<slimfaas>/wake-function/<functionName> -
Response:
204 (No Content)
This is handy if you want to ensure the function is running before real traffic arrives.
4. Listing Functions
SlimFaas exposes a route to check the readiness status of all registered functions:
-
Route:
GET http://<slimfaas>/status-functions -
Response: An array of objects with details like
NumberReady,numberRequested,PodType,Visibility, etc.
[
{
"NumberReady": 1,
"NumberRequested": 1,
"PodType": "Deployment",
"Visibility": "Public",
"Name": "fibonacci1"
},
...
]
5. Private vs. Public Functions
By default, functions are Public (accessible from anywhere). You can specify them as Private—restricting access to calls originating from within the same namespace.
metadata:
annotations:
SlimFaas/DefaultVisibility: "Private"
# or define paths:
SlimFaas/PathsStartWithVisibility: "Private:/mypath,Public:/otherpath"
SlimFaas/DefaultTrusted: "Trusted"
This helps you control which services can call certain endpoints.
An Untrusted function will be considered as outside the namespace and will not be able to access Private actions. By default, a function is Trusted.
metadata:
annotations:
SlimFaas/DefaultTrusted: "Trusted" # Trusted or Untrusted
6. Function Configuration
You can configure the synchronous HTTP timeout and the retry policies used by asynchronous and publish calls with SlimFaas/Configuration:
{
"DefaultSync": {
"HttpTimeout": 120
},
"DefaultAsync": {
"HttpTimeout": 120,
"TimeoutRetries": [2,4,8],
"HttpStatusRetries": [500,502,503]
},
"DefaultPublish": {
"HttpTimeout": 120,
"TimeoutRetries": [2,4,8],
"HttpStatusRetries": [500,502,503]
}
}
Synchronous calls make exactly one HTTP request and never retry. DefaultSync therefore supports only HttpTimeout.
TimeoutRetries defines the delays in seconds between attempts for asynchronous and publish calls. HttpStatusRetries lists the HTTP statuses that trigger those retries.
Every section is optional. When a section or property is omitted, SlimFaas applies its defaults. For example, the following configuration customizes only publish calls; sync and async keep their default 120-second timeout, and async keeps its default retry policy:
{
"DefaultPublish": {
"HttpTimeout": 15,
"TimeoutRetries": [1,2,4],
"HttpStatusRetries": [500,502,503]
}
}
7. The DependsOn Annotation
You can also add a DependsOn annotation to specify that your function should wait for certain other pods to be ready before it scales up from zero. For example:
metadata:
annotations:
SlimFaas/Function: "true"
SlimFaas/ReplicasMin: "0"
SlimFaas/ReplicasAtStart: "1"
# ...
SlimFaas/DependsOn: "mysql,fibonacci2"
- mysql and fibonacci2 are the names of other deployments/statefulsets in the same namespace.
- SlimFaas will not scale the current function (e.g.,
fibonacci1) unless all pods listed inDependsOnare in a ready state and meet their own minimum replicas.
This is useful in scenarios where your function must not start until a database or another dependent function is confirmed running.
8. Scheduling Function Wake-Up and Scale-Down
If you want your function to automatically wake at a specific time or change its scale-down timeout based on the time of day, use the SlimFaas/Schedule annotation with a JSON configuration. This feature is especially useful for workloads with predictable peak/off-peak hours.
Example Annotation
metadata:
annotations:
SlimFaas/Schedule: >
{
"TimeZoneID": "Europe/Paris",
"Default": {
"WakeUp": ["07:00"],
"ScaleDownTimeout": [
{ "Time": "07:00", "Value": 20 },
{ "Time": "21:00", "Value": 10 }
]
}
}
Configuration Details
-
TimeZoneIDDefines which IANA time zone to use (e.g.,"Europe/Paris"). You can see the full list of valid time zone IDs here: https://nodatime.org/TimeZones -
WakeUpAn array of times (HH:mm) at which the function should be woken up automatically. For example,"07:00"means that each day at 07:00 local time, the function will scale to itsReplicasAtStartvalue (rather than remain at zero). -
ScaleDownTimeoutAn array of objects containing:Time: A local time string (e.g.,"07:00").Value: The inactivity timeout (in seconds) that applies after this time.- For instance,
{"Time":"07:00","Value":20}sets a 20-second inactivity timeout from 07:00 until another time checkpoint is reached. {"Time":"21:00","Value":10}sets a 10-second inactivity timeout from 21:00 onward.
- For instance,
How It Works
- At each specified time, SlimFaas updates the function’s wake-up behavior or scale-down timeout in accordance with the schedule.
- Waking up a function ensures at least one replica is running at that time.
- ScaleDownTimeout adjusts how quickly the function is allowed to scale back to zero if there is no traffic.
Example Use Case
- 07:00: Wake up the function to be immediately available for peak morning traffic. The inactivity timeout becomes 20 seconds. If no traffic arrives for 20 seconds, the function could scale back to zero.
- 21:00: Reduce the inactivity timeout to 10 seconds, allowing a quicker scale-down in the evening/off-peak period.
This scheduling feature helps you maintain availability during predictable high-demand periods while efficiently saving resources during low-demand times.
9. Key Annotations for Functions
Before you start calling functions, ensure you add the necessary annotations to your Kubernetes Deployments or StatefulSets:
-
SlimFaas/Function: "true"Activates SlimFaas auto-scaling and routing for this pod. Without this annotation, SlimFaas will ignore the pod. -
SlimFaas/ReplicasMin: "0"The minimum number of replicas to maintain for the function. Setting0allows the function to scale down to zero after inactivity. -
SlimFaas/ReplicasAtStart: "1"The number of replicas to initially wake up to when traffic arrives or when manually woken. Typically set to1. -
SlimFaas/TimeoutSecondBeforeSetReplicasMin: "300"The number of inactivity seconds after which the function will scale down toReplicasMin. (Default is often300seconds.) -
SlimFaas/NumberParallelRequest: "10"The maximum number of concurrent requests allowed for all replicas. Additional requests will queue until a slot frees up. -
SlimFaas/NumberParallelRequestPerPod: "10": The maximum number of concurrent requests allowed per pod. Additional requests will queue until a slot frees up.
# Example snippet from a Deployment
metadata:
annotations:
SlimFaas/Function: "true"
SlimFaas/ReplicasMin: "0"
SlimFaas/ReplicasAtStart: "1"
SlimFaas/TimeoutSecondBeforeSetReplicasMin: "300"
SlimFaas/NumberParallelRequest: "10"
SlimFaas/NumberParallelRequestPerPod: "10"
10. Asynchronous Function Execution: Control Callback Mode
SlimFaas supports asynchronous function execution, allowing a function pod to take control of when the final result is returned. This pattern is well suited for long-running tasks, external system calls, or workflows that cannot complete immediately.
How It Works
-
The client (or another service) sends a request to SlimFaas:
POST /async-function/<function-name>/<path> -
SlimFaas forwards the request to the function pod and attaches multiple headers:
SlimFaas-Element-Id: <generated-id> Slimfaas-Last-Try: true|false SlimFaas-Try-Number: <attempt-number>These headers provide important context to the function:
SlimFaas-Element-Id: Unique identifier for this execution instanceSlimfaas-Last-Try: Boolean (lowercase string) indicating if this is the final retry attempt ("true"or"false")SlimFaas-Try-Number: Zero-based attempt number (e.g.,"0"for first attempt,"1"for first retry, etc.)
-
If the function wants to run control the callback, it must explicitly:
- Return
HTTP 202 Acceptedinstead of a final result. - Take responsibility for sending a callback when the result is ready.
Returning 202 is the key trigger that enables callback mode.
- Return
-
When the function completes its work:
-
On success:
POST /async-function-callback/<function-name>/<SlimFaas-Element-Id>/success -
On failure:
POST /async-function-callback/<function-name>/<SlimFaas-Element-Id>/error
-
-
If the timeout configured in SlimFaas expires before any callback is received, the execution is marked as failed.
Sequence Example
Key Points
| Element | Description |
|---|---|
| Returning HTTP 202 | This explicitly activates asynchronous callback mode |
| SlimFaas-Element-Id header | Allows the function to reference the execution instance in its callback |
| Slimfaas-Last-Try header | Indicates if this is the final retry attempt ("true" or "false") |
| SlimFaas-Try-Number header | Shows the current attempt number (starts at "0") |
| Function controls completion | The function decides when to send success/error notification |
| Timeout handling | If no callback is received within the configured timeout, SlimFaas marks the execution as failed |
HTTP Headers Sent to Functions
SlimFaas automatically injects the following headers when forwarding requests to your function pods:
SlimFaas-Element-Id
- Type: String (UUID)
- Purpose: Unique identifier for this specific execution instance
- Usage: Required when sending callbacks to SlimFaas
- Example:
SlimFaas-Element-Id: 550e8400-e29b-41d4-a716-446655440000
Slimfaas-Last-Try
- Type: String (
"true"or"false") - Purpose: Indicates whether this is the final retry attempt
- Usage: Helps functions adjust their behavior on the last attempt (e.g., send alerts, use fallback logic)
- Example:
- First attempt:
Slimfaas-Last-Try: false - After all retries exhausted:
Slimfaas-Last-Try: true
- First attempt:
SlimFaas-Try-Number
- Type: String (numeric)
- Purpose: Zero-based counter of the current attempt
- Usage: Track how many times the request has been retried
- Examples:
- First attempt:
SlimFaas-Try-Number: 0 - First retry:
SlimFaas-Try-Number: 1 - Second retry:
SlimFaas-Try-Number: 2
- First attempt:
Example in Function Code (C#):
app.MapPost("/process", (HttpContext context) =>
{
var elementId = context.Request.Headers["SlimFaas-Element-Id"].FirstOrDefault();
var isLastTry = context.Request.Headers["Slimfaas-Last-Try"].FirstOrDefault() == "true";
var tryNumber = int.Parse(context.Request.Headers["SlimFaas-Try-Number"].FirstOrDefault() ?? "0");
if (isLastTry)
{
// Last attempt - maybe send an alert or use fallback logic
logger.LogWarning("Final retry attempt {TryNumber} for {ElementId}", tryNumber, elementId);
}
// Process the request...
return Results.Accepted(); // Enable callback mode
});
Example in Function Code (Node.js):
app.post('/process', (req, res) => {
const elementId = req.headers['slimfaas-element-id'];
const isLastTry = req.headers['slimfaas-last-try'] === 'true';
const tryNumber = parseInt(req.headers['slimfaas-try-number'] || '0');
if (isLastTry) {
// Last attempt - adjust behavior accordingly
console.warn(`Final retry attempt ${tryNumber} for ${elementId}`);
}
// Process the request...
res.status(202).send(); // Enable callback mode
});
When to Use
Choose this mode when your function:
- Performs long-running or deferred processing
- Depends on external systems (queues, schedulers, batching, GPU workloads, etc.)
- Should not block the client during execution