Precomputed Tiles: Moving Work Out of the Request Path

Introduction
At Axiom, we aim to revolutionize how people make sense of their data. To achieve that, we provide immersive experiences across different data types, from neighborhood boundaries and demographic layers to traffic patterns and points of interest.
These systems rely heavily on smooth interactions: panning, zooming, and navigating across different regions without delays.
To support this, we use a combination of rendering approaches that balance flexibility and performance depending on the type of data being visualized.
As datasets grew and usage increased, we started noticing performance issues, slow tile loads, lag when revisiting areas. All of it traced back to the same thing: dynamically generated tiles for geometry that rarely changes.
In this blog, we shed light on how we approached building a more scalable geospatial system and why precomputed tiles were a key part of that shift.
Some of the challenges we faced:
- slow tile loading
- lag when revisiting the same area
- increased load on the database
- inconsistent caching behavior
At that point, it became clear:
the system works, but it doesn't scale efficiently for more demanding geospatial workloads.
Current Architecture
At Axiom, polygon and complex geometry layers are rendered using a tile-based approach.
This is a common pattern in geospatial systems when dealing with large or detailed geometries, where rendering raw data directly on the frontend becomes inefficient.
Tile-Based Rendering (Vector Tiles)
In this model:
- geometries are stored in a spatial database (e.g., PostGIS)
- a tile server such as pg_tileserv generates vector tiles (MVT)
- the frontend loads and renders these tiles using a mapping library
The flow looks like:
database → tile server → vector tiles → frontend
Instead of sending full geometry data, the system only sends the portion of data needed for the current map view, split into tiles.
On-the-Fly Tile Generation
A key detail in this architecture is that tiles are generated on demand.
When a tile is requested, the tile server queries the database, processes the geometry, and returns the result as a vector tile.
This means that:
- tiles are not precomputed or stored
- generation happens at request time
- the system depends on database queries for each tile
While this model improves performance compared to raw data rendering, it still relies on on-demand tile generation.
This means:
- every pan or zoom triggers new tile requests
- tiles are generated dynamically when they are not already cached
- tile generation depends on database queries and geometry processing
While caching layers (browser, CDN, or database) can reduce repeated work, the system still fundamentally relies on generating tiles at request time.
As datasets grow and usage increases, this can become a bottleneck — especially for complex geometries or high concurrency scenarios.
The Problem with On-Demand Tiles
While tile-based rendering improves performance compared to sending full datasets, relying on on-demand tile generation introduces new challenges as the system grows.
At Axiom, we started noticing these issues more clearly as our datasets became larger and usage increased.
Repeated Work
Each time a tile is requested and not already cached, the system needs to:
- query the database
- process and clip geometries
- encode the result into a vector tile
This means the same work can be repeated multiple times for the same areas, especially when users navigate back and forth across the map.
Database Load
Because tile generation depends on database queries, increased interaction leads to increased load on the database.
As more users explore the map:
- more tile requests are triggered
- more queries are executed
- more resources are consumed
Over time, this can impact overall system performance.
At this point, we realized:
the bottleneck is not just data size — it’s the repeated computation of static geometry.
Most geometries (like boundaries) do not change frequently, yet they are generated again and again.
Moving from On-Demand to Precomputed Tiles
To address these limitations, we started exploring a different approach:
generating tiles ahead of time instead of on demand.
This leads to the concept of precomputed tiles.
What Are Precomputed Tiles?
Instead of generating tiles every time a request is made, tiles are:
- generated once from the dataset
- stored as static files
- served directly when requested
This shifts the system from:
compute on every request → to → compute once, reuse many times
How It Works
The workflow changes from real-time generation to an offline pipeline:
- Data Extraction
The required geometry is exported from the database - Tile Generation
Tools such as Tippecanoe are used to convert the data into vector tiles - Packaging
Tiles are bundled into a format like PMTiles - Storage & Delivery
The tiles are uploaded to object storage and served via a CDN

New Request Flow
With this approach, the runtime flow becomes:
CDN → precomputed tiles → frontend

There is no need to query the database or generate tiles at request time.
Why This Works Better
Moving to precomputed tiles changes how the system behaves at runtime.
Instead of generating tiles for each request, the system simply serves already prepared data. This removes a significant amount of work from the critical path.
Faster Loading
Tiles can be delivered immediately without querying the database or processing geometry.
This results in lower latency, especially during map navigation like panning and zooming.
Reduced Database Load
With on-demand tiles, each uncached request may trigger a database query.
With precomputed tiles:
- tile generation happens once during preprocessing
- repeated requests do not increase database load
This makes the system more stable under higher usage.
Better Caching and Distribution
Because tiles are static, they can be efficiently cached and served through a CDN.
This leads to:
- higher cache hit rates
- faster delivery
- more consistent performance across users
Trade-offs
While precomputed tiles improve performance and scalability, they also introduce new trade-offs.
Data Freshness
Since tiles are generated in advance, they can become outdated when the underlying data changes.
This means:
- updates are not reflected immediately
- tiles need to be regenerated to stay in sync
Added Pipeline Complexity
The system now requires a preprocessing step to generate tiles.
This introduces:
- additional tooling and infrastructure
- background jobs or workflows
- monitoring for tile generation
Less Flexibility
With on-demand tiles, changes to queries or logic are reflected immediately.
With precomputed tiles:
- changes require regenerating tiles
- iteration becomes slightly slower
Conclusion
Switching to precomputed tiles removed a class of problems we were solving over and over at runtime. The architecture became simpler to reason about, easier to cache, and able to scale without adding database pressure.
That said, it’s not a universal answer. For data that changes frequently like real-time events, on-demand generation still makes sense. The right model depends on how often your data changes versus how often it’s read.
In our case, applying this approach to relatively stable geometries was a natural starting point. Next, we’re exploring incremental tile regeneration pipelines, so updates can propagate faster without rebuilding everything from scratch.
If you're looking for a way to make sense of your data, reach out!
