Node.js ingestion and services
The backend is where telemetry stops being a stream of numbers and starts being something a person can act on. We keep the ingest path thin and boring, and put the interesting logic somewhere it can be tested.
The common failure is a single service that accepts MQTT, validates payloads, evaluates rules, writes to Postgres and serves the dashboard. It works at fifty devices and falls over at five thousand, and by then it cannot be split apart without a rewrite.
What the work actually involves
The ingest tier
- MQTT broker with per-device X.509 authentication and topic-level authorisation
- Schema validation with versioning, so old firmware keeps working after a payload change
- Backpressure into a durable buffer rather than dropping messages under a spike
- A dead-letter path that keeps bad payloads for inspection instead of discarding them
- Time-series writes batched for throughput, with original device timestamps preserved
The domain services
- Device registry covering the full lifecycle: manufactured, provisioned, deployed, retired
- Rules engine with versioned thresholds and a full audit trail of who changed what
- Alert routing with escalation, acknowledgement and suppression windows
- OTA campaign orchestration with cohorts, canaries and automatic halt on failure rate
- Reporting and export APIs, plus integrations with ERP, billing and ticketing systems
What you get to keep
- Services in your repository with the CI pipeline that builds them
- OpenAPI and AsyncAPI specifications generated from the code
- A fleet simulator that reproduces your load profile at ten times launch size
- Load test results with the breaking point identified, not just the happy path
- Runbook for the on-call engineer, written for someone who was not on the project
Because the work is overwhelmingly I/O rather than computation: thousands of idle connections, small frequent messages, and fan-out to live dashboards. Node handles that shape well, the ecosystem for MQTT and streaming is mature, and one language across backend and frontend keeps a small team fast. Where we need heavy number crunching we put it in a Python or Rust service and keep the rest as it is.
No. Kafka earns its place above roughly two thousand messages a second or when several consumers need the same stream. Below that, Redis Streams or a Postgres-backed queue is less to operate and we will say so.
What this normally sits next to
These capabilities come up in almost every engagement that includes the one above.
React operator consoles
The screen your team actually uses: live fleet map, per-device history, alarm rules, firmware rollouts and role-based access. Built for a shift supervisor on a ten-year-old browser, not for a demo.
Cloud, deployment and monitoring
Infrastructure as code, one-command environments, and dashboards that page a human before a customer notices. We hand you the keys and the runbook, or keep running it for you.
Talk to the engineers who do this work
The first call is with whoever would lead the build, not an account manager. Bring the constraint you think is going to be a problem.