How SlimFaas Works (Architecture)

For local development with a reproducible three-node Raft cluster, see Running a three-node SlimFaas cluster locally. For the sync, async, set, and file memory workload, see Reproducing SlimFaas memory workloads locally.

Under the hood, SlimFaas is an HTTP proxy that intercepts requests for your functions, jobs, or events. It handles scaling, routing, and state management.


1. Core Concepts

  1. SlimFaas Pod Runs as a Deployment or StatefulSet (commonly 3 replicas in production). Each pod has internal workers:

    • SlimWorker: Handles async call processing.
    • ClusterMembershipAnnounceWorker: Lets a follower announce itself to an existing SlimData leader.
    • SlimDataMembershipReconciliationWorker: Lets the leader reconcile the Raft membership with the orchestrator topology, including delayed scale-down removal.
    • HistorySynchronizationWorker: Syncs request history and logs.
    • ReplicasSynchronizationWorker: Keeps track of your function pods’ replicas and statuses in Kubernetes.
    • ReplicasScaleWorker: If the SlimFaas pod is leader, it scales up/down your function pods.
  2. SlimData A built-in key-value store based on Raft, provided by .NET’s dotNext. This database is crucial for consistent state among SlimFaas pods. Each node keeps the current state in memory and persists replicated commands in a write-ahead log (WAL).

SlimData recovery

DotNext 6.4.1 chooses the synchronization path internally. SlimFaas supplies warmupRounds (100 by default): a restarted member first attempts WAL backtracking and can fall back to DotNext snapshot recovery when the gap is larger than the configured search window. There is no public API in this version to force a snapshot for a particular follower.

The SlimData diagnostics metrics expose the locally measurable recovery state: slimdata_raft_local_apply_lag (local WAL entries pending application, not leader/follower replication lag), slimdata_raft_wal_generation_rate, slimdata_raft_catch_up_rate, slimdata_raft_catch_up_cannot_converge, slimdata_raft_recovery_mode{mode="wal|restoring|unknown"}, and slimdata_raft_recovery_duration_seconds. The convergence gauge is an early-warning signal, not a membership failure: it is set when the observed local apply rate is below the observed WAL generation rate. If an alternate audit-trail implementation does not expose an applied index, lag and recovery metrics remain zero because that state cannot be measured safely.

  1. Annotations Add or remove SlimFaas annotations on your pods/Deployments to control scaling, concurrency, visibility, and timeouts.

  2. Public vs. Private Restricts who can access a function/job (any external caller vs. same-namespace or trusted pods).


SlimData WAL and snapshots

DotNext supports two WAL memory-management strategies. SlimFaas selects the strategy with SlimData:WalMemoryManagement:

  • SharedMemory is the default. It writes directly to memory-mapped WAL files so the operating system can reclaim or flush mapped pages under memory pressure.
  • PrivateMemory uses private temporary buffers and favors write throughput, at the cost of higher RAM consumption.

SlimData creates a streaming snapshot when either 32 MiB of successfully applied WAL entries or 500 successfully applied entries have accumulated, whichever occurs first. A snapshot compacts the preceding Raft log window; the byte and entry counters restart after the snapshot request or a snapshot restore.

{
  "SlimData": {
    "WalMemoryManagement": "SharedMemory",
    "SnapshotIntervalEntries": 500,
    "SnapshotIntervalBytes": 33554432
  }
}

The equivalent environment variables are:

SlimData__WalMemoryManagement=SharedMemory
SlimData__SnapshotIntervalEntries=500
SlimData__SnapshotIntervalBytes=33554432

WalMemoryManagement accepts only PrivateMemory and SharedMemory, case-insensitively. Snapshot intervals must be strictly positive. Invalid values stop startup with a configuration error. Changing the memory strategy does not change the WAL format and does not require a data migration.

The current byte window and the cause of the latest snapshot request are exposed as slimdata_wal_bytes_since_snapshot and slimdata_snapshot_last_trigger{cause="bytes|entries|incompatible"}.


2. Request Flow

Synchronous HTTP Calls

  1. Client → SlimFaas GET /function/<functionName>/...
  2. SlimFaas ensures the target function is scaled up and ready.
  3. SlimFaas → Function Wait for the function’s response.
  4. SlimFaas returns the function’s response to the client.

Synchronous HTTP call

Asynchronous HTTP Calls

  1. Client → SlimFaas GET /async-function/<functionName>/... (returns immediately with 202 Accepted).
  2. SlimFaas durably enqueues the request in SlimData, then returns 202.
  3. The committed mutation signals the HTTP and WebSocket workers immediately; periodic polling remains only as a recovery fallback.
  4. SlimWorker reads one lightweight queue snapshot (counts, running IDs, and IP reservations, without payload copies), then dispatches while respecting concurrency and least-connections limits.
  5. Completions enter a mailbox, release response/body/cancellation resources immediately, and are committed back to SlimData in grouped callbacks. Queue callback application uses a single indexed pass; terminal offload cleanup runs in a separate mailbox after that durable callback, with best-effort remote file deletion and batched orphan-metadata cleanup.
  6. Function handles each request. Results completed after a leadership loss are discarded locally so the current leader owns retry/callback decisions.

Asynchronous HTTP call

Publish/Subscribe (Events)

  1. Client → SlimFaas POST /publish-event/<eventName> with JSON payload.
  2. SlimFaas synchronously broadcasts the payload to each subscribed function’s replicas.
  3. Each replica processes the event and responds individually to SlimFaas.

Synchronous event publication


3. Scaling Logic

  • Scale to 0 after a defined inactivity (SlimFaas/TimeoutSecondBeforeSetReplicasMin).
  • Scale from 0 to 1+ when a new request arrives or wake-function is called.
  • Optional: Use standard K8s Horizontal Pod Autoscalers or KEDA if you need more advanced scaling triggers.

4. CPU-Aware Rate Limiting

SlimFaas includes built-in load shedding to protect your cluster during traffic spikes by automatically rejecting requests when CPU usage exceeds configurable thresholds.

Key Features

  • Hysteresis support: Prevents rapid toggling between limited and normal states with separate high/low thresholds.
  • Port-specific: Applies to all SlimFaas ports except the SlimData internal port (used for cluster coordination).
  • Path exclusions: Configurable list of paths to exclude (e.g., health checks, metrics endpoints).
  • Native AOT compatible: Minimal performance overhead.

How It Works

  1. Monitoring: A background service continuously samples CPU usage at a configurable interval.
  2. Activation: When CPU exceeds the CpuHighThreshold, the middleware starts rejecting requests with 429 Too Many Requests.
  3. Deactivation: When CPU drops below the CpuLowThreshold, normal processing resumes.
  4. Exemptions: The SlimData port (used for internal cluster communication) is always exempt from rate limiting.

Configuration

Add the following to your appsettings.json:

{
  "SlimFaas": {
    "RateLimiting": {
      "Enabled": true,
      "CpuHighThreshold": 80.0,
      "CpuLowThreshold": 60.0,
      "SampleIntervalMs": 1000,
      "RetryAfterSeconds": 30,
      "ExcludedPaths": [
        "/health",
        "/ready",
        "/metrics"
      ]
    }
  }
}

Parameters:

  • Enabled (bool): Enable or disable CPU rate limiting.
  • CpuHighThreshold (double, 0-100): CPU percentage that triggers rate limiting.
  • CpuLowThreshold (double, 0-100): CPU percentage that stops rate limiting (must be < CpuHighThreshold).
  • SampleIntervalMs (int, ≥100): How often to sample CPU usage (milliseconds).
  • RetryAfterSeconds (int?, optional): Value for the Retry-After header in 429 responses.
  • ExcludedPaths (string[]): List of paths that bypass rate limiting (e.g., health checks).

Validation:

  • CpuLowThreshold < CpuHighThreshold
  • Both thresholds must be between 0 and 100
  • SampleIntervalMs must be ≥ 100

Port Exemption

The CPU rate limiting middleware automatically exempts the SlimData port (configured via publicEndPoint in your SlimData configuration). This ensures that:

  • Internal cluster coordination is never throttled
  • Raft consensus and state synchronization continue uninterrupted
  • Only external/public traffic on other ports is subject to rate limiting

This design keeps your control plane healthy even under extreme load.


5. Build & Technology Stack

SlimFaas is developed in .NET, chosen for its:

  • High performance in web APIs. SlimFaas is compile in Ahead Of Time (AOT) mode which produce a native application.
  • Excellent concurrency model.
  • Constant improvements in speed and memory usage.
  • Compact container images.

That’s the architecture in a nutshell! SlimFaas ensures your functions and jobs scale efficiently while remaining lightweight and easy to set up.