When we started building Navionyx, our GPS tracking platform, everything looked simple.
A few vehicles, a few thousand location points, and basic tracking dashboards.
Fast forward a few months โ we were dealing with:
-
100+ million GPS records
-
GBs of time-series data
-
Thousands of devices sending data continuously
-
A real-time dashboard that users expected to load instantly
This is the story of how we redesigned our database, architecture, and query strategy to scale reliably โ without overengineering or throwing unnecessary infrastructure at the problem.
๐ The Real Challenge of GPS Systems
GPS tracking systems are deceptively hard to scale.
They are:
-
Write-heavy โ constant inserts from devices
-
Read-heavy โ dashboards polling frequently
-
Time-series driven โ data grows forever
At scale, naรฏve designs lead to:
-
Slow
ORDER BYqueries -
Full table scans
-
EC2 CPU spikes
-
Dashboards taking seconds to load
We had to rethink how GPS data should be stored and queried.
๐ง Designing GPS Data as Time-Series (Not Relational)
One of the first decisions we made was treating GPS data as append-only time-series data.
Key principles:
-
No updates, only inserts
-
Optimize for โlatest point per vehicleโ
-
Avoid unnecessary joins
Simplified schema:
This allowed PostgreSQL to do what it does best โ fast writes and indexed reads.
โก PostgreSQL: The Unsung Hero
PostgreSQL handled our scale surprisingly well โ once we used it properly.
Key features we relied on:
-
Composite indexes
-
Descending indexes
-
Table partitioning
-
Materialized views
-
Aggressive query optimization
One of the most impactful indexes we added:
This alone reduced our latest GPS fetch time from seconds to milliseconds.

๐งฉ Partitioning: Making 100M Rows Feel Manageable
Instead of one massive table, we partitioned GPS data by date.
Why date-based partitioning works well for GPS:
-
Queries usually target recent data
-
Old data is rarely accessed
-
Automatic partition pruning reduces scans
Results:
-
Smaller index sizes per partition
-
Faster deletes and archiving
-
Predictable performance even as data grows
๐ The Dashboard Bottleneck
Our fleet dashboard shows:
-
Total vehicles
-
Running
-
Stopped
-
Idle
-
Offline
Originally, each refresh recalculated this from raw GPS data.
That meant:
-
Repeating expensive queries
-
CPU-heavy aggregations
-
Slower response times during peak load
We needed a smarter approach.
๐ฅ Materialized Views: The Game Changer
Instead of calculating vehicle states repeatedly, we pre-computed them.
We introduced a materialized view that:
-
Stores the latest GPS point per vehicle
-
Derives vehicle status
-
Refreshes periodically
Now dashboard queries became trivial:
โก Instant results. Minimal load.

โ๏ธ AWS EC2: Scaling Without Overengineering
We ran PostgreSQL on dedicated EC2 instances, tuned for database workloads.
Key decisions:
-
High-RAM EC2 instance
-
SSD-backed storage
-
Proper PostgreSQL memory tuning
-
Connection pooling (PgBouncer)
Instead of blindly scaling horizontally, we:
-
Optimized queries first
-
Reduced unnecessary load
-
Scaled only when metrics justified it

๐ฆ Handling GBs of GPS Data Efficiently
Why this architecture works:
-
Append-only writes keep inserts fast
-
Indexes optimize the most common access patterns
-
Partitioning keeps queries scoped
-
Materialized views eliminate runtime computation
PostgreSQL proved it can comfortably handle:
-
Hundreds of millions of rows
-
Continuous writes
-
Real-time dashboards
๐ง Key Takeaways
If youโre building a GPS or telemetry system:
-
Model data for access patterns, not just schema
-
Index for โlatest recordโ queries
-
Use materialized views for dashboards
-
Partition early โ not after performance breaks
-
PostgreSQL is far more powerful than people assume
With the right design, you donโt need exotic databases โ just well-used fundamentals.


