Autoscaling
The scaler keeps the fleet the right size and shape. It ingests usage, evaluates rules on a loop, and provisions or removes nodes across cloud providers — all without touching the request path.
Multi-cloud provisioning
Section titled “Multi-cloud provisioning”The scaler provisions edge nodes through a pluggable provider interface. Built-in targets include AWS, Fly, Hetzner, Vultr, DigitalOcean, E2B, and India-first providers (E2E, Vyom, Utho, Iotamine) — and any provider can be added by implementing the interface. A selector maps a desired (region, ip_type) to a concrete provider and instance.
Self-registration & membership
Section titled “Self-registration & membership”A freshly provisioned node boots, runs the edge binary, and registers itself in etcd with a short-lived lease (TTL ~30s). If a node crashes, its lease expires and it drops out of the fleet automatically. The scaler keeps an in-memory snapshot of membership by watching the etcd prefix.
A node that doesn’t appear within a boot timeout (~5 min) is treated as failed, and its VM is cleaned up.
Scaling rules
Section titled “Scaling rules”The scaler evaluates rules on a loop (every ~30s), enforcing per-spec and per-node cooldowns so it never thrashes:
| Trigger | Action |
|---|---|
| Constraint gap — a required (region, ip_type) is below its minimum | Scale up: provision a node for that spec |
| Unhealthy node — error rate > 30% over 5 min, or p99 latency > 5s under low load | Recycle: boot a replacement first, then remove the old node |
| Idle node — no traffic for ~30 min | Scale down: remove it |
Recycling provisions the replacement before removing the old node, so there’s no capacity gap.
Reconciliation
Section titled “Reconciliation”A slower reconcile loop (every ~60s) re-checks for constraint gaps, cleans up orphaned VMs (provisioned but never registered) and ghost nodes (registered but gone), keeping cloud state and etcd in sync.
Metrics feedback to core
Section titled “Metrics feedback to core”The same metrics the scaler computes are exposed over a small gRPC API that core
polls every few seconds, so lowest_latency routing and
the circuit breaker act on fresh per-node health.