Plans and limits¶
The hosted SimpleOTA service ships with three plans.
| Feature | Free | Maker | Pro |
|---|---|---|---|
| Monthly price | $0 | $12 | $39 |
| Active devices | 5 | 50 | 500 |
| Firmware uploads / month | 10 | 100 | 500 |
| Max artifact size | 16 MB | 16 MB | 32 MB |
| Email support | No | ✅ | ✅ |
Need more than 500 devices? Contact us for custom limits, storage, and SLA.
Counters¶
- Active devices = devices in your projects with
active = true. Aggregated across all projects you own. - Artifacts this month = artifacts uploaded in the current calendar month (UTC). The window resets at 00:00 UTC on the 1st of every month, the same boundary for every user regardless of plan or Stripe billing cycle.
- Max artifact size = the largest single firmware binary you can upload, checked on every upload path. It is generous for an ESP32 application image: a 4 MB flash gives roughly a 1.25 MB app partition, and an 8 MB flash about 3 MB. Together with the monthly upload cap it is what bounds how much storage an account can consume.
The dashboard shows usage bars on the Billing page.
What happens when I hit a cap?¶
| Cap | Behavior |
|---|---|
| Device cap (auto-register) | The device gets 200 with "status": "over_limit". No row is created, and the device is not bricked. |
| Device cap (manual create) | 400, "Device limit reached for the current plan." |
| Artifact cap | 400, "monthly artifact upload limit reached for current plan; …". The upload form blocks too. |
| Artifact size cap | 400, naming the size and the plan's limit. Nothing is stored, so it does not consume an upload from your monthly allowance. |
Errors are matched by HTTP status, not by a machine-readable code: see Errors.
Downgrade behavior¶
Switching from Pro → Maker → Free deactivates devices to fit the new cap, oldest-active-wins:
- Order all your active devices by
created_atascending. - Keep the oldest N as
active = true, where N is the new cap. - The rest flip to
active = false.
Devices that go inactive are not deleted. Upgrading later (or going into the dashboard and toggling them) reactivates them. The deactivation is recorded in the audit log.
Cancellation¶
Clicking Cancel sets cancel_at_period_end = true in Stripe. You
keep paid features until the period ends; on customer.subscription.deleted
the user falls back to Free and the downgrade behavior above runs.