What we build

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.

Node 20NestJSFastifyTypeScriptMQTTKafkaTimescaleDB
The problem we usually find

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.

9k/speak messages ingested on a delivered platform
38 mstypical p95 acknowledgement latency
10×launch load we test against before go-live
In practice

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
On delivery

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
Why Node.js for an IoT backend?

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.

Do we have to use Kafka?

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.

All common questions

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.

See engagement models