Reference

Architecture

MeteorCloud is modular. Planes do not import each other’s internals; they talk over HTTP, MQTT, and configuration. Product-level overview: Concepts.

Three planes

PlaneDeployable unitCompose
Control planeIdentity, tenancy, devices, audit, MQTT policy, ingest, operator APIdeploy/compose/control-plane.yml
Data planeEMQX client, publish/watch, ingest forwarddeploy/compose/data-plane.yml
Device planemeteorcli on the edge devicenot a Compose service

Operator console: Vite/React in console/ — browser → control-plane API only. See Console.

┌─────────────────┐     ┌─────────────────┐     ┌──────────────────────┐
│  Device plane   │     │   Data plane    │     │   Control plane      │
│  (meteorcli)    │     │  (MQTT gateway) │     │  (API + Postgres)    │
└────────┬────────┘     └────────┬────────┘     └──────────┬───────────┘
         │                       │                         │
         │  HTTPS enroll /       │                         │
         │  heartbeat            ├────────────────────────►│
         │────────────────────────────────────────────────►│
         │                       │                         │
         │  MQTT ──► EMQX ──────►│  HTTP ingest ──────────►│
         │◄── commands ◄─ EMQX ◄─│◄── HTTP publish ────────│

Deployment paths

Same images and settings, two installers:

PathWhereFiles
Docker Compose + AnsibleOne VM, EC2, or on-prem serverdeploy/compose/, deploy/ansible/
Kubernetes + HelmAn existing cluster (MeteorCloud does not provision clusters)deploy/kubernetes/helm/meteorcloud/

On AWS, edge-installer creates the EC2 host with Terraform and runs the Ansible path. See Deployment, Kubernetes, and Services.

Control plane

src/control-plane/app/
├── api/rest/         # health
├── ports/            # MQTTGateway, RateLimiter, OTAProvider
├── adapters/         # data-plane HTTP, redis/memory, s3/filesystem, ota=none
├── identity/
├── tenancy/
├── devices/
├── audit/
├── mqtt/             # ACL, credentials, ingest, SSE hub
├── core/
└── main.py

PostgreSQL is the control-plane database. Vendor systems (EMQX, Redis, future OTA) sit behind ports — no generic DatabaseProvider.

Data plane

Python FastAPI process. Owns the platform MQTT session. Forwards each inbound payload to POST {CONTROL_PLANE_URL}/internal/mqtt/ingest. Contract: contracts/mqtt-http.md.

Keep one data-plane MQTT subscriber until shared subscriptions exist.

Provider selection

PortImplementedReserved (fail fast)
PersistencePostgreSQL—
RateLimiterredis, memory—
MQTTGatewayData-plane HTTP → EMQXother broker names
Telemetry last-valuePostgreSQL columns on Devicetimescale, clickhouse
OTAProvidernonemender and others later
ObjectStorages3, filesystem—

Artifact binaries live in object storage; PostgreSQL keeps metadata and storage_key. See Artifacts.

Kubernetes

The Helm chart deploys backend, console, and (with MQTT) data-plane and EMQX as separate Deployments. API and console scale independently; the data-plane MQTT consumer stays at 1 replica until shared subscriptions exist. See Kubernetes.

Architecture · MeteorCloud