Skip to content

Dynamic tiling ecosystem comparison

This page compares the two main FastAPI-based ecosystems for serving Zarr-backed datacubes as tiles: TiTiler (Development Seed) and Xpublish with its plugins (the xpublish-community org, Earthmover, and the wider xarray community). For per-ecosystem detail see the TiTiler ecosystem overview and the Xpublish ecosystem overview. For the client-side equivalent (visualization libraries that bypass a tile server entirely), see the client-side rendering comparison.

Which should I use?

  • TiTilerCOG/STAC-first, GDAL-native raster, fast cold start, and a mature cloud-deploy story (Docker, Lambda/ECS). Reach for it when your data is regular or projected raster, or when you need NASA CMR or ESA EOPF integrations.
  • Xpublish — xarray-native, with first-class support for irregular grids (curvilinear, triangular FVCOM, HEALPix, cubed-sphere) and a pick-your-protocol plugin model (tiles, WMS, OGC EDR, OPeNDAP). Reach for it for operational scientific data on its native grid.

TiTiler is intended for public-facing slippy-map tiles. Xpublish for research access to the same data on native grids.

Summary

TiTiler » Xpublish »
Maintainer Development Seed xpublish-community (Joe Hamman, Alex Kerney); code © UCAR; xpublish-tiles by Earthmover
Shape Layered Python stack: rio-tilertitiler.coretitiler.xarray → applications (titiler.application, titiler-cmr, titiler-multidim, titiler-eopf) Small xpublish core with independent plugins (xpublish-tiles, xpublish-wms, xpublish-edr, opendap-protocol)
Dataset identity Client-supplied per request: ?url=… on generic endpoints (titiler-eopf/titiler-cmr are path/search exceptions) Server-published namespace: /datasets/{id}/…, ids resolved server-side
Rendering engine rio-tiler + GDAL/rasterio Datashader
Primary inputs COG, STAC; Zarr/NetCDF/Icechunk via titiler.xarray Xarray-native: Zarr (primary), NetCDF, Icechunk
Grid topologies Regular and projected lat/lon are first-class; curvilinear limited; unstructured out of scope Regular, curvilinear, FVCOM triangular, SELFE, 2D non-dimensional, HEALPix, cubed-sphere, polar
Reprojection GDAL warp (full kernel set) Custom pyproj: separable 4326→3857 fast path, blocked thread-pool transform for general CRS
Tile endpoints XYZ, WMTS, TileJSON, POST /statistics; no vector tiles XYZ, WMTS, OGC Tiles 1.0, full WMS, MVT/GeoJSON vector tiles, OGC EDR, OPeNDAP
Conventions CF via rioxarray (basic), STAC native CF via cf-xarray (full), flag_values/flag_meanings/flag_colors for categorical, no STAC
Caching Redis (dataset-level) Plugin-configurable; xpublish-tiles keys on _xpublish_id + dim + variable
First request Fast Slow (Numba JIT; warm-up required)
Deployment Official Docker images, AWS Lambda/ECS CDK examples No official images; deployment is hands-on
License MIT Apache 2.0

How they differ

The deeper detail lives on the per-ecosystem pages (linked from the table headers and under Related); this section covers only the contrasts that don't belong to either page on its own.

Structure. TiTiler is a vertically layered stack — rio-tiler and titiler.core at the base, titiler.xarray adding Zarr/NetCDF, opinionated applications on top — with a COG-first lineage that shows up as GDAL-native raster handling, STAC integration, and a deep set of cloud-deploy recipes. Xpublish is a small core plus independent, mix-and-match plugins (tiles, WMS, EDR, OPeNDAP), centered on xarray-native scientific data and the irregular grid topologies operational geoscience uses.

Architecture of the TiTiler layered stack alongside the Xpublish core-plus-plugins stack

Who names the dataset. This is the difference that drives deployment and security. TiTiler takes the data location as a per-request query parameter (?url=…) on generic, stateless endpoints, so any worker serves any request and the service drops onto Lambda/ECS behind a CDN — at the cost of exposing the location in the URL and an open fetch surface that needs allowed-host limits. Xpublish publishes a server-owned namespace (/datasets/{id}/…) resolved server-side, so the dataset is curated by the operator and stays resident in the process — which is what enables its _xpublish_id caching and stateful EDR/OPeNDAP queries, at the cost of stateful replicas that must share the same registry. (titiler-eopf and titiler-cmr are path/search exceptions to TiTiler's query-parameter model.)

Rendering engine. The engines mirror that split. TiTiler renders through GDAL via rio-tiler (full resampling kernels, band-math expressions, fast cold start). Xpublish-tiles renders through Datashader with Numba Just-in-Time (JIT) and a custom pyproj reprojection — a slow first request in exchange for renderers that handle curvilinear, triangular, and other unstructured grids GDAL can't, picking an engine per grid type.

Grid topologies — regular, curvilinear, triangular, HEALPix, cubed-sphere — and which stack supports each

Picking the right tool

  • COG and STAC are the design center, or you need a mix of raster formats from one stack: TiTiler.
  • Operational scientific data on irregular grids (FVCOM, SELFE, ROMS curvilinear, HEALPix, ICON triangular): Xpublish with xpublish-tiles and/or xpublish-wms.
  • OGC EDR queries (position/area/cube extraction, time-series, profiles): Xpublish with xpublish-edr.
  • OPeNDAP clients: Xpublish with opendap-protocol.
  • Categorical raster styling from CF flag_values/flag_meanings/flag_colors, vector tiles, or a legend endpoint: Xpublish-tiles.
  • NASA CMR or ESA EOPF data: TiTiler via titiler-cmr, or titiler-eopf respectively.
  • Dynamic tiling of xarray-readable stores (Zarr, NetCDF): titiler-multidim

A common hybrid is TiTiler for public-facing slippy-map tiles (where its Redis cache and Lambda/ECS deploy story shine) and Xpublish-tiles/EDR for research-oriented access to the same datasets on their native grids.