SimpleOTA
Arduino & ESP-IDF  ·  Free to start

ESP32 OTA shouldn't need
an infrastructure team.

Upload, deploy, done. From a single board to a full fleet.

POST /api/v1/ota/check/
// Device polls your project endpoint
POST /api/v1/ota/check/
Authorization: Bearer proj_live_••••••••
Content-Type: application/json

{
  "device_id": "esp32-a4cf12b8f3",
  "current_build_number": 7
}

// SimpleOTA responds with a short-lived pre-signed URL
{
  "update_available": true,
  "build_number": 12,
  "url": "https://firmware.simpleota.com/builds/...?sig=...",
  "checksum": "8f3c...",
  "size": 1287456
}

Everything you need, nothing you don't

Designed for makers and teams shipping real firmware to real devices.

Instant OTA

Upload a binary and it's available to your fleet within seconds. No servers to manage, no file hosting to configure.

Canary rollouts

Roll out to 5% of your fleet, watch for issues, then promote to 100%. Deterministic device bucketing: the same device always gets the same build.

Direct delivery

Firmware downloads via short-lived pre-signed URLs. Binary data flows from object storage directly to the device; our servers never touch it.

Arduino & ESP-IDF

Drop the SimpleOTAClient Arduino library into your sketch for a managed update loop, or call /api/v1/ota/check/ directly from ESP-IDF (first-party ESP-IDF library coming soon).

How it works

From binary upload to device running new firmware, in six steps.

ESP32 device Simple OTA Object Storage firmware binary POST /ota/check/ pre-signed URL binary download (direct, not via SimpleOTA)
1

Upload

Push a firmware binary and manifest via the dashboard or dev API. A monotonic build number is assigned automatically.

2

Deploy

Create a deployment: pick target device groups, a release channel, and a rollout percentage (e.g. 5%).

3

Devices check in

Each device periodically calls POST /api/v1/ota/check/ with its current build number.

4

Engine decides

SimpleOTA checks firmware compatibility and the device's deterministic cohort. Devices outside the rollout receive a no-update response.

5

Pre-signed URL

Eligible devices receive a time-limited pre-signed URL pointing directly at object storage. It expires automatically; the binary can't be fetched indefinitely.

6

Direct download

The binary flows from storage straight to the device. Our servers are never in the data path: no bottleneck, no bandwidth cost.

Why not just host a .bin file?

A file host delivers bytes. SimpleOTA runs the control plane around them.

Device identity

Every device is a tracked entity. You know which firmware each unit is running, when it last checked in, and whether it applied the update.

Build ordering

Monotonic build numbers ensure devices always move forward, never accidentally downgrade, and the engine can compare exactly what is installed against what is available.

Compatibility checks

Firmware targets specific chip families, board IDs, hardware revisions, and partition profiles. Incompatible builds are never offered, regardless of rollout state.

Staged rollouts

Start at 5%, watch the failure rate, then promote. A deterministic hash assigns each device to a stable cohort so rollout percentages are consistent across polls.

Per-device progress

Devices report back at every stage: offered, downloaded, flashed, validated, rebooting, confirmed. You see where each device is in the update cycle and can pause or cancel mid-flight.

Automatic rollback

New firmware runs as a trial. If it does not confirm itself healthy within a configurable timeout, the device boots back into the previous partition. The dashboard reflects the outcome automatically, no server action required.

Expiring URLs

Each download link is time-limited and single-use in intent. There is no permanent public URL to guess, share, or cache. A device that misses the window must check in again to get a fresh one.

Audit trail

Every deployment, promotion, and rollback is logged. You have a full history of what was pushed, to which devices, when, and whether each device confirmed the update.

Know your fit

SimpleOTA is deliberately focused. Here is what that means in practice.

Built for

  • Makers shipping a real product to paying customers
  • Consultants managing firmware across multiple client projects
  • Indie hardware founders who need fleet ops without a DevOps team
  • Small commercial fleets (tens to thousands of ESP32 devices)
  • Teams that need staged rollouts, not just a download link

Not built for

  • Full IoT platforms (no MQTT, no telemetry, no device shadows)
  • Remote command and control of live devices
  • Sensor data ingestion or time-series storage
  • Non-ESP32 targets (other microcontrollers are on the roadmap, not yet supported)
  • Enterprises requiring on-premises deployment (contact us)

Simple pricing

Free to start, with paid plans as your fleet grows. No credit card required.

Frequently asked questions

What ESP32 frameworks are supported?

Both Arduino and ESP-IDF are supported. Select your framework when creating a project. For Arduino, install our SimpleOTAClient library (PlatformIO: lib_deps = https://github.com/xanderwasserman/SimpleOTAClient-Arduino.git) and the polling and update loop is handled for you. For ESP-IDF, any HTTP client (such as esp_http_client) works against the same API; a first-party ESP-IDF library is on the roadmap.

How does OTA delivery actually work?

Your device polls /api/v1/ota/check/ with its current build number. SimpleOTA decides if an update is available and, if so, responds with a short-lived pre-signed URL pointing directly at object storage. The device downloads the binary straight from there. SimpleOTA servers never proxy the firmware bytes.

Can I roll back to an older firmware version?

On-device (Arduino, SimpleOTAClient v0.2.0+): Yes, automatically. After each OTA the new image is a trial: if confirmRunning() is not called within the confirm timeout (default 300 s), the library reboots the device back into the previous partition. No server action required. Fleet-level: Re-upload the previous binary as a new artifact; it is assigned a higher build number and can be deployed like any other release. Devices that already confirmed the bad build receive the corrected release through normal deployment. This keeps the audit trail clean.

Is there really a free plan? What's the catch?

Yes, free with no credit card required. The free plan supports up to 5 devices and 10 firmware uploads per month, which is plenty for personal projects and prototypes. Upgrade to a paid plan when your fleet grows.

What is the difference between SimpleOTA and the ArduinoOTA library?

The ArduinoOTA.h library (part of the ESP32 Arduino core) performs OTA updates over your local Wi-Fi network using mDNS. It works well during development but requires the device and your computer to be on the same network. There is no internet delivery, no fleet management, no version tracking, and no deployment history. SimpleOTA delivers firmware over the internet to devices anywhere in the world, and adds build ordering, device groups, canary rollouts, and a full deployment audit trail.

What is the difference between SimpleOTA and Arduino Cloud OTA?

Arduino Cloud OTA is a feature inside the broader Arduino Cloud platform. It delivers firmware over the internet via S3, but requires you to compile and upload your sketch through the Arduino Cloud editor; you cannot bring a binary built with PlatformIO, ESP-IDF, or a CI pipeline. Devices must be enrolled in Arduino Cloud as connected Things. SimpleOTA is build-system agnostic: compile with PlatformIO, ESP-IDF, Arduino IDE, or any CI system and upload the binary directly. There is no platform lock-in, no IoT variable system required, and SimpleOTA adds canary rollouts, device groups, and fleet-level version tracking that Arduino Cloud OTA does not provide.

Does SimpleOTA work with PlatformIO?

Yes. SimpleOTA is build-system agnostic. Compile your firmware with PlatformIO as you normally would, then upload the resulting .bin file via the SimpleOTA dashboard or dev API. For Arduino projects, add the SimpleOTAClient library to your platformio.ini via lib_deps = https://github.com/xanderwasserman/SimpleOTAClient-Arduino.git and the OTA polling loop is handled automatically.

How do I update multiple ESP32 devices at the same time?

SimpleOTA handles fleet updates through Deployments. Create a deployment targeting a device group or release channel, set a rollout percentage (for example 5% for a canary, or 100% for a full release), and devices update themselves the next time they check in. You do not push to devices; devices pull from the platform, so scale is not a concern on your end.

Ready to ship firmware OTA?

Create a free account and have your first device updating in minutes.