Ship ML models to phones and edge devices in stages, watch how each version behaves, and roll back automatically when one is worse.

FleetML is self-hosted and open source under Apache-2.0, and works with any model file. Android and iOS apps get it through two SDKs, Linux machines through an agent, and the server starts with one docker compose command.

Latest release v0.10.7 · Install the CLI

The dashboard's Deployments page: a canary of iris 2.0.0 rolling out at stage 1 of 3 (10%) in region us; an earlier canary of iris 2.0.0 in region eu marked ROLLED_BACK because its error rate of 12.5% was above the 5% gate at stage 1; and two COMPLETE deployments of iris 1.0.0.
The dashboard: a canary the health gate rolled back (error rate 12.5% above the 5% gate), next to one still rolling out.

A recorded run

What a rollout looks like

scripts/demo.sh against a real server and twenty simulated devices that use the same protocol as the SDKs: the model published, the fleet on 1.0.0, then a canary of a broken 2.0.0 that the health gate rolls back. Every line below is a line the script printed; the strip follows the deployment through the states the dashboard shows.

▶ 1. Publish three versions of a model
  $ fleetml push models/iris/iris_v1.tflite --model iris --version 1.0.0
  ✓ Pushed models/iris/iris_v1.tflite → iris v1.0.0 (INT8)
  $ fleetml push models/iris/iris_v2.tflite --model iris --version 2.0.0
  ✓ Pushed models/iris/iris_v2.tflite → iris v2.0.0 (INT8)
  each file was sha256-verified on upload; only verified files are ever sent to devices
▶ 2. Twenty devices enroll and get 1.0.0
  $ fleetml simulate --devices 20 --label app=demo   # simulated phones: real protocol, real downloads
  $ POST /api/v1/deployments  {version: 1.0.0, target: app=demo}
  fleet: iris 1.0.0 on 20
▶ 4. A canary of 2.0.0 with a health gate; 2.0.0 is broken
  $ POST /api/v1/deployments  {version: 2.0.0, strategy: CANARY 25% -> 100%, gate: errors <= 5% over 30 events, else ROLLBACK}
  fleet: iris 1.0.0 on 12, iris 2.0.0 on 8   (the canary cohort only)
  deployment ROLLED_BACK: error rate 22.92% exceeds threshold 5.00% (11/48 events from 8 cohort devices)
  fleet: iris 1.0.0 on 20, nobody outside the canary ever saw 2.0.0
It needs Docker, Go and jq: ./scripts/demo.sh from a clone.
The whole run, as printed (it goes on to drift and an A/B test)

▶ Starting the dev stack and a demo server

▶ 1. Publish three versions of a model
  $ fleetml push models/iris/iris_v1.tflite --model iris --version 1.0.0
  ✓ Pushed models/iris/iris_v1.tflite → iris v1.0.0 (INT8)
  $ fleetml push models/iris/iris_v2.tflite --model iris --version 2.0.0
  ✓ Pushed models/iris/iris_v2.tflite → iris v2.0.0 (INT8)
  $ fleetml push models/iris/iris_v2.tflite --model iris --version 2.1.0
  ✓ Pushed models/iris/iris_v2.tflite → iris v2.1.0 (INT8)
  each file was sha256-verified on upload; only verified files are ever sent to devices

▶ 2. Twenty devices enroll and get 1.0.0
  $ fleetml simulate --devices 20 --label app=demo   # simulated phones: real protocol, real downloads
  $ POST /api/v1/deployments  {version: 1.0.0, target: app=demo}
  fleet: iris 1.0.0 on 20

▶ 3. Drift: the last day's latency against the week before
  latency drift for 1.0.0: NONE (PSI 0.026)
  now the devices slow down (say, after an OS update)...
  latency drift for 1.0.0: CRITICAL (PSI 8.511)
  a change into CRITICAL is sent as an alert: 1 drift alert(s) on NATS

▶ 4. A canary of 2.0.0 with a health gate; 2.0.0 is broken
  $ POST /api/v1/deployments  {version: 2.0.0, strategy: CANARY 25% -> 100%, gate: errors <= 5% over 30 events, else ROLLBACK}
  fleet: iris 1.0.0 on 12, iris 2.0.0 on 8   (the canary cohort only)
  deployment ROLLED_BACK: error rate 22.92% exceeds threshold 5.00% (11/48 events from 8 cohort devices)
  fleet: iris 1.0.0 on 20, nobody outside the canary ever saw 2.0.0

▶ 5. A/B test: 1.0.0 against the fixed 2.1.0
  $ POST /api/v1/experiments  {control: 1.0.0, treatment: 2.1.0, target: app=demo, min_sample_size: 300}
  control 1.0.0:   350 inferences, mean 34 ms
  treatment 2.1.0: 350 inferences, mean 13 ms
  Welch t-test p < 0.0001, recommendation: ADOPT_TREATMENT
  $ POST /api/v1/deployments  {version: 2.1.0, target: app=demo}
  fleet: iris 2.1.0 on 20

▶ Done in 30s (plus 17s of setup)
  The same steps work against your devices with the Android and iOS SDKs (docs/ANDROID_SDK.md, docs/IOS_SDK.md).

One line is left out: the setup line with the server's local ports.

See it on your own phone

Get started with a phone in place of the Linux agent. The Android SDK is tested on a physical phone and the emulator, the iOS SDK on a physical phone and simulators.

Android

  1. Check the tools: JDK 17 and adb.
  2. Start FleetML: the first start takes a few minutes.
  3. Get the CLI, checked against the release's checksums.
  4. Publish the sample model and deploy it.
  5. Put the phone on it: the sample app over a USB cable, until the model is active on the phone.
  6. See it in the dashboard: one device, one COMPLETE deployment of iris 1.0.0.
  7. Clean up: the app, the forwards, the server and all its data.
The Android sample app: a device online, Active model iris 2.0.1, the Classify sample flower button, the result virginica 100.0% in 549 microseconds, and its log.
Android

iOS

  1. Check the tools, with XcodeGen for the sample app's Xcode project.
  2. Start FleetML: the first start takes a few minutes.
  3. Get the CLI, checked against the release's checksums.
  4. Publish the sample model and deploy it, the Core ML build of it.
  5. Put the simulator on it: the sample app, until the SDK logs the model active.
  6. Put your iPhone on it: pick the phone, build and install the app, then start it.
  7. See it in the dashboard: the iPhone, and one COMPLETE deployment of iris 1.0.0.
  8. Clean up: the app on the simulator, the build, the server and all its data.
The iOS sample app: a device online, Active model iris 2.0.0, Classify sample flower, and the result virginica 100.0% in 90 microseconds.
iOS

What it does

Rollouts that stop themselves

The end-to-end tests in the repository cover every one of these.

Canary rollouts with a health gate

The gate watches the canary cohort's error rate, and optionally p95 latency, and rolls back or pauses. It looks only at the new version's telemetry from the devices the current stage exposes, so errors from devices outside the cohort never count.

Health gate

Automatic rollback

A rollback, by the gate or by hand, marks the deployment ROLLED_BACK and sends devices back to the previous version, with its URL and sha256. The revert is urgent: devices fetch it on any network, and usually still have it cached as their last-known-good version.

Rollback

Drift detection

PSI on latency, confidence and input features, the last 24 hours against the 7 days before, with an alert on CRITICAL. Every check's PSI is kept, and the Drift page draws it over time.

Tour step 5

The dashboard

Drift, experiments and rollbacks in the dashboard

Models, deployments, experiments, drift and alert sinks, with server-side login sessions, on a desktop or a phone. These are the repository's own screenshots.

The Drift page for iris 1.0.0: confidence PSI 2.347 and latency PSI 2.377, both CRITICAL, from 240 baseline against 280 current events, with a history table of the two checks and their baseline and current windows.
Drift: PSI per metric, the last day against the week before.

How it works

One server, your devices, and a health gate on every staged rollout

Devices heartbeat with the models they run and receive assignments: what to load, update or unload, with presigned download URLs and their experiment arms. Three background loops advance rollouts through the health gate, evaluate experiments and check drift.

FleetML's components and a staged rollout Android and iOS apps with the SDKs and Linux machines with the agent talk to the FleetML server over gRPC; the dashboard and the CLI use its REST API. The server keeps its data in Postgres with TimescaleDB, sends telemetry and alerts through NATS, and hands out presigned URLs, with which the CLI uploads and devices download model files from an S3-compatible object store. Below: a new version goes to a canary stage; the health gate checks it; if it passes, the next stage follows until every device has it; if it fails, the deployment rolls back and devices return to the previous version. Android / iOS SDKin your app, beside its runtime Linux agentstatic binary, systemd Dashboard, CLI, Pythonyou and your pipelines FleetML serverGo; rollouts, experiments,drift, health gate Postgres + TimescaleDBregistry, telemetry NATStelemetry, alerts S3-compatible storemodel files gRPCgRPCREST the CLI uploads and devices download model files with presigned URLs A staged rollout New versionpushed, verified Canary stagea share of devices Health gatecohort error rate, p95 Next stage, up to 100%the gate checks each stage Rolled backdevices return to the previous version pass fail FleetML's components and a staged rollout Android and iOS apps with the SDKs, Linux machines with the agent, and the dashboard, CLI and Python client talk to the FleetML server, devices over gRPC and you over REST. The server uses Postgres with TimescaleDB, NATS and an S3-compatible store; the CLI uploads and devices download model files with presigned URLs. Below: a new version goes to a canary stage and the health gate; if it passes, the next stage follows up to 100%; if it fails, the deployment rolls back and devices return to the previous version. Android / iOS SDKin your app, beside its runtime Linux agentstatic binary, systemd Dashboard, CLI, Pythonyou and your pipelines gRPC from devices,REST from you FleetML serverGo; rollouts, experiments,drift, health gate Postgres + TimescaleDBregistry, telemetry NATStelemetry, alerts S3-compatible storemodel files The CLI uploads and devices download modelfiles with presigned URLs. A staged rollout New versionpushed, verified Canary stagea share of devices Health gatecohort error rate, p95 pass Next stage, up to 100% fail Rolled backdevices return to the previous version

Architecture has the request paths, data model, device protocol and trust boundaries; Rollouts has the strategies, the health gate and the statistics.

Platforms

Install

Each snippet below is taken from the README or the guide it links when this page is built.

CLI Get started, step 3

Linux, macOS and Windows archives on GitHub Releases, checked against the release's SHA256SUMS:

bash
OS=$(uname -s | tr '[:upper:]' '[:lower:]'); ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
curl -fsSLO "https://github.com/fleetml/fleetml/releases/latest/download/fleetml-$OS-$ARCH.tar.gz"
curl -fsSLO https://github.com/fleetml/fleetml/releases/latest/download/SHA256SUMS
grep " fleetml-$OS-$ARCH.tar.gz\$" SHA256SUMS | shasum -a 256 -c
mkdir -p ~/.local/bin && tar -xzf "fleetml-$OS-$ARCH.tar.gz" -C ~/.local/bin fleetml
rm "fleetml-$OS-$ARCH.tar.gz" SHA256SUMS
export PATH="$HOME/.local/bin:$PATH"
fleetml version

On Windows, Get started runs in the Ubuntu shell of WSL 2 with Docker Desktop, PowerShell runs the Windows CLI, and a Windows browser shows the dashboard: On Windows.

Android Android guide

From Maven Central (with mavenCentral() in the app's repositories; the app needs compileSdk 34 or later and minSdk 26):

build.gradle.kts
implementation("dev.fleetml:fleetml-sdk:0.10.7")
implementation("org.tensorflow:tensorflow-lite:2.17.0") // if you run TFLite models

iOS iOS guide

In Xcode with File → Add Package Dependencies and the repository URL (Dependency Rule Up to Next Major Version from 0.10.7):

Swift Package Manager
https://github.com/fleetml/fleetml

Linux agent Linux guide

On the machine, the latest release, checked, then installed as root (amd64 or arm64):

bash
ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
curl -fsSLO "https://github.com/fleetml/fleetml/releases/latest/download/fleetml-agent-linux-$ARCH.tar.gz"
curl -fsSLO https://github.com/fleetml/fleetml/releases/latest/download/SHA256SUMS
grep " fleetml-agent-linux-$ARCH.tar.gz\$" SHA256SUMS | sha256sum -c
mkdir -p fleetml-agent && tar -xzf "fleetml-agent-linux-$ARCH.tar.gz" -C fleetml-agent
sudo ./fleetml-agent/install.sh ./fleetml-agent/fleetml-agent
fleetml-agent -version

Python Python client

For pipelines and notebooks: pip install fleetml, then, from the root of the clone:

Python
import time
from fleetml import FleetML
fm = FleetML()  # the server and key from FLEETML_SERVER and FLEETML_API_KEY
p = fm.projects.create(f"pipeline-{time.strftime('%Y%m%d-%H%M%S')}")  # names are unique per server
v = fm.push("models/iris/iris_v1.tflite", project=p.id, model="iris", version="1.0.0")
fm.deployments.start(fm.deployments.create(p.id, v.id).id)

Kubernetes Helm chart

The server, the dashboard and optional bundled Postgres, NATS and SeaweedFS, tested end to end in kind. From the chart README's Get started:

bash
REST=38080 GRPC=39090 S3=39100 DASH=38800
helm install fleetml deploy/helm/fleetml -n fleetml --create-namespace \
  -f fleetml-secrets.yaml --set s3.publicEndpoint=localhost:$S3

Is it for you

What it is, and what it is not

A good fit

  • You run models on phones or edge devices and would otherwise build staged rollouts, rollback and drift monitoring yourself.
  • Your apps are Android (minSdk 26) or iOS (15 and later), or your machines run Linux on amd64 or arm64.
  • You keep your runtime: FleetML works with any model file, and your app runs the model with its own runtime.
  • You want it on your infrastructure: you run the server, its Postgres, NATS and object store yourself, with Docker Compose or the Helm chart, so your models and telemetry never leave it.

Not what it is

  • Not an inference runtime: your app or inference process keeps running the model with the runtime you already use.
  • Not a model trainer or converter: it starts from a file you already have, in any format.
  • Not a hosted service, and it does not terminate TLS itself: put its ports behind a TLS proxy before exposing them.

Trust

What you can check

Apache License 2.0

The server, SDKs, agent, CLI, dashboard and chart are in one public repository.

LICENSE

Verified downloads

Devices verify each download and keep the previous version if the new one does not load; models are signed per project and checked before download.

Artifact signing

Release checksums

Every release lists its archives in SHA256SUMS, and the install lines check them.

Latest release

Security policy

Report vulnerabilities privately to security@fleetml.dev or through GitHub's private reporting; the policy has the threat model.

SECURITY.md

Tests and CI

The end-to-end tests in test/e2e cover every feature above, and make e2e runs them; the CI workflow is on GitHub Actions.

CI on GitHub Actions

Changelog

What each release changed.

Changelog

Status

Where it is today

v0.10.7

Released 2026-10-29. Changelog

Pre-1.0

Security fixes go into the latest release only. SECURITY.md

Tested

The Android SDK on a physical phone and the emulator, the iOS SDK on a physical phone and simulators, the Helm chart end to end in kind.

On the roadmap

Sigstore as an alternative to the built-in signing keys, and organisations with single sign-on. Nothing on it is in a release yet. Roadmap

Contact

Anything about FleetML: questions, ideas, what breaks, what you use today instead.

hello@fleetml.dev