Prompt
I’m designing an IoT ingestion system with out-of-order events and many devices. What database architecture would you suggest?
Latest observation
For an IoT ingestion system with many devices and out-of-order events, I’d generally recommend a streaming-first, append-only architecture backed by a time-series–friendly storage layer, rather than trying to enforce strict ordering at write time.
Recommended architecture
1. Ingest through a durable event log
Use a broker such as:
- Kafka
- Pulsar
- Kinesis
This gives you:
- High write throughput
- Buffering for bursts
- Replayability
- Decoupling of producers from storage/processing
Partition by device_id or tenant_id + device_id so related events land together as much as possible.
2. Store raw events as immutable append-only records
Do not update rows in place for every late event unless you truly need transactional state.
Write events with:
device_idevent_timefrom the deviceingest_time- sequence number if available
- payload
This supports:
- Out-of-order arrivals
- Auditing/reprocessing
- Late-arriving correction logic
3. Use a storage engine optimized for time-series / wide-column writes
Good options:
Option A: Time-series DB
- TimescaleDB (PostgreSQL-based)
- InfluxDB
- QuestDB
Best if:
- You need SQL-like analytics
- You want time-window queries
- You expect moderate to high scale
- You want easier operations than a custom pipeline
TimescaleDB is especially nice if you want relational features plus hypertables and compression.
Option B: Wide-column / NoSQL
- Cassandra
- ScyllaDB
- DynamoDB
Best if:
- You need very high write throughput
- Large number of devices
- Mostly key-based access patterns
- Predictable query shapes
Typical pattern:
- Partition by
device_id - Cluster by
event_timedescending - Keep raw append-only events
This handles out-of-order events well because you’re not relying on strict sequential inserts.
Option C: Lakehouse for long-term storage + analytics
- S3/GCS/Azure Blob + Parquet
- Query with Trino, Spark, Athena, BigQuery, Databricks
Best if:
- You want cheap retention
- Large-scale analytics
- Historical reprocessing
- ML feature generation
Many IoT systems use a dual-write pattern:
- Hot store for recent/query-heavy data
- Data lake for cheap long-term storage
Handling out-of-order events
Keep both event time and ingest time
Always store:
event_time: when the sensor says it happenedingest_time: when your system received it
This lets you:
- Query by true time
- Measure lateness
- Rebuild state if late events arrive
Design for idempotency
Give each event a unique identifier, such as:
(device_id, sequence_number)- UUID from device
(device_id, event_time, payload_hash)if nothing else exists
Then deduplicate in ingestion/processing.
Windowed correction
If you maintain aggregates:
- Recompute in sliding windows
- Allow late-arrival grace periods
- Use event-time processing semantics
Suggested overall pattern
If you need operational queries + analytics
A strong default is:
- Kafka for ingestion
- TimescaleDB or Cassandra/Scylla for hot operational querying
- S3 + Parquet + Trino/Spark for long-term analytics
This gives you:
- Real-time ingestion
- Tolerance for out-of-order events
- Efficient recent-data reads
- Cheap historical storage
Which database should you choose?
Choose TimescaleDB if:
- You want SQL
- Need flexible querying and aggregates
- Scale is high but not extreme
- You value developer productivity
Choose Cassandra/ScyllaDB if:
- Massive write throughput
- Simple query patterns
- Many devices
- You need horizontal scale first
Choose a lakehouse if:
- Analytics/history are the main goal
- You can tolerate higher read latency
- You want cheapest storage at scale
Practical schema suggestion
For a hot store:
device_events (
device_id text,
event_time timestamptz,
ingest_time timestamptz,
event_id text,
payload jsonb,
PRIMARY KEY (device_id, event_time, event_id)
)
If using a wide-column DB, make sure the primary key matches its partitioning/clustering model.
My default recommendation
If you’re starting fresh and want a balanced architecture:
- Kafka as the ingestion backbone
- TimescaleDB for recent/queryable data
- S3 + Parquet for long-term storage and analytics
If your write volume is extremely high and query needs are simple:
- Kafka + Cassandra/ScyllaDB + data lake
If you want, I can also propose:
- a reference architecture diagram,
- schema design for a specific DB, or
- a decision matrix comparing TimescaleDB vs Cassandra vs lakehouse for your use case.