Real-time mapping

Bring live data into any map

What does this solution do?

This solution is a code-based architecture that enables advanced users to build performant and lightweight, real-time data-join using Mapbox. In other words, we’re making it easier for you to join a live dataset — like the reporting of election returns by county — to geometries in a Mapbox tileset.

When joining spatial data on the fly, users often need to generate long expressions in order to visualize the data on a map, and if the dataset is large, the process can be slow. This solution offers a performant approach to data-join, using Mapbox GL JS feature-state.

Last Updated:
January 14, 2020
Start building
Source code on Github

Solution details

The solution repository contains an example application that follows the recommended approach to data-join using feature-state. In the example, the application populates and colors US counties based on voter participation data. The solution is performant because it abstracts the live data from its geometries. We’re able to accomplish this abstraction because:

  • The geometry is tiled in advance
  • The live data is served to clients via an API
  • The two parts of the data are joined at run-time using feature-state

These aspects can be used to enable a variety of real-time visualizations. For more information on the application’s architecture, refer to the README in the Github repo.

Understanding the data

When mapping live data on unchanging geometries, timely and performant updates are key. That’s where data-joins come in.

Here’s how it works: Two sources of data need to be joined at runtime to create the real-time visualization. One is the source geometry, which is served as tiles from Mapbox. The other is a sequence of real-time updates, which come from an API.

The geometry

Tilesets API data preparation flow

The source geometry goes through a series of transformations before being tiled and served by Mapbox. We first make sure that it has a unique identifier (e.g. FIPS) and then format it as a GeoJSON sequence. Once uploaded, the Tilesets API lets us further filter the data and limit what is served in our tiles to only what our application needs. You can find an example of this process in the data directory of the solution’s repository.

Live data and map rendering

Separate sources for static geometry and real-time properties
Joining real-time messages with static geometry on ID

At runtime, the browser joins live data streamed from an API to tiled geometry hosted on Mapbox, and styles the data based on updated real-time values using data-driven styling and expressions. When new data is received from the server, the feature-state of the relevant counties gets updated with the new information. The Mapbox renderer then re-draws only the changed counties based on their new state. For more information about using feature-state for rendering, read this series on election mapping.

Example details

The example uses county geometry from Census Bureau TIGER line boundaries, and identifies geometry by each county’s FIPS code. The election data is mocked from actual results from the 2016 general presidential election. We upload the boundaries using the Tilesets API and a simple recipe to ensure that the tiles store only the data we need.

Client-server communication

We establish a one-way flow of information from the server as election data is only traveling one way — from API to client. We use server-sent events (SSE) as an efficient approach to provide a stream of real-time data. SSE maintains a single HTTP connection between the server and each client, and allows cellular devices to save battery power when no new data is being sent.

On the client, we use the EventSource API to receive SSE. As events are sent from the server, we make them available to the rest of our application through an RXJS Observable. The observable provides a consistent interface to the server updates and prevents race conditions when the application is initialized. We subscribe to events from the observable to update our map’s style.

Your live data server might require clients to poll for new data or receive data through a socket connection. Those functions can still be connected to an observable to make updating the rest of your application’s state straightforward. However new data is delivered to your client application, you still update the map through the same feature-state interface.

Technical information

What you’ll need:

Usage considerations

When using this solution, you will be making API calls to Mapbox and will be responsible for any usage that exceeds our developer free tier.

  • Mapbox usage: The example client application depends on Mapbox GL-JS and is available to all users.
  • Mapbox GL-JS uses the Maps APIs to load vector tiles.
    The first 50,000 map loads, per month, are free of charge.
  • Tilesets API is used for uploading and tiling spatial data
    The Tilesets API is free to use while in public beta.
  • Rate Limits: All APIs are set to the default rate limits.
    Map loads are limited to 100,000 requests per minute.
    Tileset creation, source upload, and publishing are limited to 3 requests per minute.
    To inquire about increasing your rate limits, please contact Sales.

For more pricing details, consult our pricing documentation.