Generating Vector Tiles with PostGIS and Python for OpenLayers Map Rendering

This gif display the interactive vector tiles stored in disk/cache rendering on openlayers map.

What are Vector Tiles?

Vector tiles are a way of storing and serving geographic data in a compact and efficient format. Unlike traditional raster tiles, which are pre-rendered images, vector tiles contain vector data that can be rendered dynamically on the client side. This means that they can be styled and labeled in real-time, allowing for interactive maps that are highly customizable and responsive to user input.

Vector tiles are typically used in web mapping applications, where they are served to the client side using technologies like Mapbox or OpenLayers. They are also used in desktop GIS software like QGIS and ArcGIS Pro.

To get full source code for this tutorial, click here.

To check the live demo for this tutorial, click here.

Why are Vector Tiles Great for Map Rendering?

Vector tiles have several advantages over traditional raster tiles:

  1. Flexible styling: Because vector tiles contain actual vector data, they can be styled in a highly flexible and customizable way. This allows for more creative and unique map designs that can be tailored to the specific needs of the application.
  2. Faster rendering: Vector tiles are smaller and more efficient than raster tiles, which means they can be rendered more quickly and with less strain on the client’s hardware.
  3. Smaller file size: Vector tiles are typically much smaller in size than raster tiles, which makes them faster to download and easier to store.
  4. Better resolution: Because vector tiles are not pre-rendered images, they can be rendered at any scale without loss of resolution or quality.
  5. Interactive: Vector tiles are interactive. We can style and interact with them on client side. In this tutorial, we will use openlayers to render and style them on the fly

This tutorial will help you to generate vector tiles and store them in local storage or cache them and directly render them in OpenLayers Map from stored location.

Generating Vector Tiles Using Python and PostGIS

In this tutorial, we will generate vector tiles for a layer hosted in postgis database and store those vector tiles in local disk and render them on web map using openlayers.

Now, let’s look at how to generate vector tiles using Python and PostGIS.

First, we need to set up a PostGIS database and connect to it using SQLAlchemy. We also need to import the necessary libraries, including GeoPandas, os and math

To generate vector tiles for a specific area of interest, we can use GeoPandas to read in our geographic data and obtain the bounding coordinates for the layers using the total_bounds function. The total_bounds function returns the minimum and maximum coordinates for all geometries within a GeoDataFrame.

By obtaining the bounding coordinates, we can limit the generation of vector tiles to only the area within those bounds. This can significantly reduce the amount of data that needs to be processed and displayed, resulting in improved performance and faster load times for the OpenLayers map.

You can also use postgis query to get the extent of a layer by using following approach

We also need to define a function called deg2num() that converts latitude, longitude, and zoom level to tile coordinates. This function takes in three arguments: lat_deg, lon_deg, and zoom. In summary, the deg2num() function converts latitude, longitude, and zoom level to tile coordinates or tile column and row number for which we have to gnerate vector tiles for a point on the Earth’s surface. These coordinates can be used to generate vector tiles using PostGIS.

We can now define the extent and zoom levels for our vector tiles. In this example, we are using the total_bounds property of our tricity GeoDataFrame to define the extent, and a list of zoom levels from 0 to 17.

Next, we define a SQL query template that fetches geometries for each zoom level. The template uses the ST_AsMVT() function from PostGIS to generate vector tiles. It also uses the ST_TileEnvelope() function to define the bounds of each tile, and the ST_Transform() function to convert the geometries to the Web Mercator projection (EPSG 3857).

  • The ST_AsMVT() function generates a vector tile by taking the geometries in a given layer and converting them to a binary format that can be displayed on a map.
  • The q subquery selects the geometries that intersect with the bounding box of a given tile, and clips and simplifies them to fit within the tile bounds.
  • The ST_Transform() function converts the geometries from their original projection to the Web Mercator projection, which is the standard projection used by most web maps.
  • The ST_TileEnvelope() function calculates the bounding box of a given tile in the Web Mercator projection.
  • The WHERE clause filters out geometries that do not intersect with the bounding box of a given tile.

Overall, the SQL query template generates vector tiles by selecting and clipping the geometries that intersect with a given tile, and converting them to the binary format used by vector tiles.

Finally, we loop through the zoom levels and tile coordinates, execute the SQL query for each tile, and save the resulting vector tile as a .mvt file.

The resulting vector tiles are saved in a directory called tiles, organized by zoom level and tile coordinate. You can see the below image for reference.

To display the generated tiles on an OpenLayers map, we can create a vector tile layer using OpenLayers and provide the path to the generated vector tiles. In this case, on line 39, the URL path for the vector tiles has been defined as ’tiles/{z}/{x}/{y}.mvt’.

This URL path is a template that will be filled with values for the zoom level (z), the tile column (x), and the tile row (y) to fetch the appropriate vector tile for the current view of the map. The .mvt file extension indicates that these are vector tiles encoded using the Mapbox Vector Tile format.

In summary, generating vector tiles using Python and PostGIS involves setting up a PostGIS database, defining the extent and zoom levels, and executing a SQL query to generate vector tiles using the ST_AsMVT() function. The resulting vector tiles can be served to web mapping applications or desktop GIS software, allowing for flexible and customizable map rendering.

I hope this tutorial will create a good foundation for you. If you want tutorials on another GIS topic or you have any queries, please send an email at

We also offer freelancing services. Please email us at for any query.

Leave a Reply Cancel reply