The device lost connection, a sensor threw an error, and the log contains 10 million records. We'll show you how to find the needle in seconds. We create IoT event logs not as a simple table, but as a full-fledged tool for incident analysis. Without proper structure and filtering, 99% of data remains unused. Our solution reduces error search time by 40%. In one project with 5 million device events per day, we implemented ClickHouse and cut query time from 3 seconds to 40 ms. Offline caching allowed technicians to view logs even in no-coverage zones — critical for field conditions.
Filtering Events Without Delays
The key to performance is correct event structure and storage choice. Minimum field set: ID, timestamp, severity level (DEBUG, INFO, WARNING, ERROR, CRITICAL), category (connection, sensor, command, firmware), and metadata. For storage we use TimescaleDB or ClickHouse — they are optimized for time series and provide queries in 80 ms even with 10 million records. Compare: regular PostgreSQL at 1 million records takes 2-3 seconds, while TimescaleDB takes 50 ms.
data class DeviceEvent( val id: Long, val deviceId: String, val timestamp: Instant, val severity: Severity, val category: String, val message: String, val metadata: Map<String, Any?> ) Client-side event filtering uses pagination and color coding. The server returns only the required range (default 50 records). The mobile app displays events with intuitive markings: gray (DEBUG), white (INFO), yellow (WARNING), red (ERROR/CRITICAL). Critical entries are always on top. For faster navigation, we use cursor-based pagination instead of offset — it's more stable under frequent new writes.
Future<List<DeviceEvent>> fetchEvents({ required String deviceId, DateTime? from, DateTime? to, List<Severity>? severities, String? searchQuery, int page = 0, int pageSize = 50, }) async { return _api.getEvents( deviceId: deviceId, from: from?.toIso8601String(), to: to?.toIso8601String(), severities: severities?.map((s) => s.name).toList(), q: searchQuery, offset: page * pageSize, limit: pageSize, ); } Importance of Offline Cache for IoT
When connection drops, users must see the latest records. We cache up to 500 latest events in SQLite using drift. Upon reconnection, the client loads new events via the since parameter. This reduces server load and ensures instant response. Offline access is critical for field technicians. Step-by-step implementation:
- Choose a local DB (SQLite).
- Create a table with event fields.
- Define eviction policy (e.g., FIFO up to 500 records).
- Implement synchronization: client sends
since— latest timestamp, server returns new events.
For finer tuning, you can use SQLite WAL mode, which speeds up writes under concurrent access. Also set indexes on timestamp and deviceId for fast lookups.
Comparison of Local vs Cloud Storage
| Parameter | Local (SQLite) | Cloud (TimescaleDB) |
|---|---|---|
| Volume | Up to 500 records | Millions of records |
| Speed | Instant access | Query ~80 ms |
| Offline | Full support | Requires network |
| Synchronization | Manual/auto | Real-time |
Which Server Storage to Choose?
| Storage | Write (op/s) | Query (ms) | Scalability |
|---|---|---|---|
| TimescaleDB | 100k | 80 | Horizontal |
| ClickHouse | 200k | 50 | Horizontal |
| MongoDB | 50k | 200 | Horizontal |
For mobile solutions with millions of records, TimescaleDB or ClickHouse are 5-10x faster than MongoDB and PostgreSQL. Using TimescaleDB instead of SQLite on the server speeds up queries by 100x at 10 million records. When choosing, consider data model: ClickHouse is better for aggregate analytical queries, TimescaleDB for point lookups.
According to TimescaleDB documentation, time series are stored efficiently via automatic time-based partitioning.
What's Included in the Work
We deliver IoT device event logging turnkey:
- Event structure and API design
- Server-side implementation (TimescaleDB/ClickHouse)
- Client-side logic in Swift, Kotlin, or Flutter
- Push notifications and deep linking integration (Universal Links / App Links)
- Caching and offline mode setup
- APK size optimization via ProGuard/R8
- Documentation and operation manual
The process includes stages: analytics → design → implementation → testing → deployment. During analytics, we clarify logging requirements, choose the stack, and after implementation we perform load testing.
Timeline: 1–2 weeks depending on complexity. Typical project cost ranges from $5,000 to $15,000. Get a consultation to evaluate your project — we'll help you with logging and propose an optimal solution.
Why Choose Us?
With many years of experience in mobile development and over 50 IoT projects delivered, we guarantee stable event logging. Our engineers are Apple and Google certified, using modern approaches: SwiftUI, Jetpack Compose, Flutter 3.x. We've been on the market for many years — a testament to our reliability.
Get a consultation: contact us to evaluate your project.







