Vector tiles and snapshots
There are two ways to get vector tiles out of Sync Server.
| Live tiles | Snapshots | |
|---|---|---|
| Freshness | Follows the cache | Frozen at build time |
| Built | On demand, per tile | Once, ahead of time |
| Cost per request | Tile generation (cached) | A read from an .mbtiles file |
| Cacheable at the edge | Partly | Fully — immutable, 1-year max-age |
| Good for | Data that changes and must look current | Big, stable basemap-ish layers under real traffic |
Live tiles
Section titled “Live tiles”/api/v0/rest/services/{baseId}/{tableName}/VectorTileServer/tiles.json → TileJSON/api/v0/rest/services/{baseId}/{tableName}/VectorTileServer/{z}/{x}/{y}.pbf(.../VectorTileServer/{layer}/{z}/{x}/{y}.pbf also works, for Esri clients that expect a
layer segment.)
Same authentication as any other read. Two paths run underneath, chosen automatically:
- PostGIS bases serve tiles natively with
ST_AsMVT, per tile, reading only the geometry that intersects the requested tile through the spatial index. No whole-table fetch. - Everything else builds tiles from the cached GeoJSON and caches the result. The tile cache is cleared whenever the table re-syncs.
A PostGIS table can be addressed by its bare name when that’s unambiguous across schemas, or as
schema.table when it isn’t.
Snapshots
Section titled “Snapshots”A snapshot is an immutable .mbtiles tileset built from a table and hosted by the server. You
create one by asking for the mbtiles export format and giving it a slug.
curl -X POST '…/rest/services/{baseId}/FeatureServer/export' \ -H 'Content-Type: application/json' -H 'Authorization: Bearer …' \ -d '{ "formats": "mbtiles", "mbtiles": { "name": "Country boundaries", "attribution": "© International Mapping", "minzoom": 0, "maxzoom": 10, "layers": [ { "tableName": "Countries", "layer": "countries", "fields": ["UID", "NAME"] } ] }, "snapshot": { "slug": "boundaries-2026q3", "public": false } }'Once the job succeeds the tileset is served at:
GET /api/v0/tiles/{baseId}/{slug}/tiles.json → TileJSON 3.0.0GET /api/v0/tiles/{baseId}/{slug}/{z}/{x}/{y}.pbf → a gzipped MVT tileA public: true snapshot needs no credentials — point MapLibre straight at the tiles.json.
Otherwise the caller authenticates for the owning base as usual.
Options
Section titled “Options”| Key | Meaning |
|---|---|
name, description, attribution |
Tileset metadata |
minzoom / maxzoom |
Defaults 0 / 12; maxzoom is overridable per layer |
layers[].tableName or layers[].layerId |
Which table becomes this MVT layer |
layers[].layer |
The MVT layer id — [A-Za-z0-9_-], so it’s style-safe |
layers[].fields |
Keep-list of properties. Omit to keep everything |
layers[].geometry |
Derive geometry from named fields for a table whose config has none |
projection |
Omit for Web Mercator; see below |
mbtiles does not accept the where / bbox / outSR / outFields export filters — it
has its own per-layer fields and projection instead.
Projections
Section titled “Projections”Web Mercator (EPSG:3857) is the default and is built with tippecanoe, which drops features by density as you zoom out. That’s what MapLibre and Mapbox GL can read.
Any other EPSG is built with GDAL’s MVT writer against a custom tiling scheme, which needs an
explicit tileOrigin (upper-left, in CRS units) and tileDim0 (the size of the single zoom-0
tile). Those tilesets are for OpenLayers/ArcGIS-style clients with custom tile grids —
MapLibre cannot read them.
Geometry from fields
Section titled “Geometry from fields”A cached table may have no geometry because its config never named coordinate fields. Rather than editing the table and forcing a re-sync, give the snapshot its own mapping:
{ "geometry": { "latitudeField": "Lat", "longitudeField": "Lon", "geometryType": "Point" } }Either a geometryField or both latitudeField and longitudeField. To see what a base has to
work with:
GET /api/v0/bases/{baseId}/geometry-sourcesManaging snapshots
Section titled “Managing snapshots”GET /api/v0/bases/{baseId}/snapshots → listPATCH /api/v0/bases/{baseId}/snapshots/{slug} → toggle public, edit name/attributionDELETE /api/v0/bases/{baseId}/snapshots/{slug} → remove the row and the fileGET /api/v0/bases/{baseId}/snapshots/{slug}/download → stream the .mbtilesReads need access to the base; writes need write access.