Planetiler & Tilemaker Workflows Jump to heading
Both of these tools do something a GeoJSON-based pipeline cannot: they read an OSM extract and emit a finished tile archive in a single pass, never materialising the enormous text intermediate that dominates the alternative. That is the reason to reach for them, and the reason their schema model looks so different from a generator that just consumes features.
The Problem This Topic Solves Jump to heading
You need a complete base map from an OSM extract, and the GeoJSON route’s intermediate files are the dominant cost — in disk, in time, or in both. Single-pass tools remove that intermediate entirely, which for a continent or the planet is the difference between a feasible build and an infeasible one.
The failure scenario is subtler than a crash. A team adopts a single-pass tool, copies an example profile, and gets a working map quickly. Six months later nobody can change what appears at zoom 10, because the cartographic rules are spread through a profile that was never read carefully and the tool rebuilds everything on every change. The trap is not the tool; it is treating the profile as configuration when it is the most important code in the pipeline.
Prerequisites Jump to heading
Understand the tile model from OSM Vector Tiles & Rendering Pipelines and the generalization vocabulary from Cartographic Generalization of OSM Data. Know how OSM elements become geometry, from Node, Way & Relation Data Model — a profile sees elements, not ready-made features.
The Two Tools, Honestly Compared Jump to heading
Planetiler is a Java application built for throughput. Its profile is Java code implementing an interface: a method called per element, returning the layers and attributes that element contributes. It uses memory-mapped node storage and a highly optimised feature store, and it will build a planet-wide tile set on a single large machine in hours rather than days. The cost of that speed is that the schema is a compiled artefact — changing a zoom threshold means rebuilding the profile.
Tilemaker is a C++ application whose profile is a Lua script plus a JSON layer configuration. The Lua functions are called per node and per way, and the JSON declares the layers with their zoom ranges. It is slower than Planetiler on very large inputs but far quicker to iterate on, because changing the schema is editing a script. For a regional map with a custom schema, that iteration speed usually matters more than raw throughput.
Node Location Storage: the Shared Constraint Jump to heading
Both tools face the same fundamental problem as any OSM parser: building way geometry requires the coordinates of every referenced node, and there are far more nodes than features. The strategies are the ones discussed in Memory-Efficient Chunk Processing, applied at tile-building scale.
Planetiler defaults to a memory-mapped array indexed by node identifier, which is fast and demands either a lot of RAM or a fast local disk with generous page cache. Tilemaker offers a choice between an in-memory store and an on-disk one, with the on-disk option making a large region feasible on a modest machine at a throughput cost.
The practical rule is the same for both: node storage is the thing that decides whether your build fits on the machine you have. Estimate it first, before choosing zoom ranges or layers, because it is the constraint that does not negotiate.
Validation and Error-Handling Matrix Jump to heading
| Condition | Root cause | Detection | Remediation |
|---|---|---|---|
| Build exhausts memory | Node store sized for a smaller region | Failure during the first read pass | Switch to on-disk node storage or add RAM |
| A layer is empty | Profile never matches its condition | Layer declared but no features written | Log match counts per layer during the profile run |
| Relations missing from output | Profile does not handle relation members | Multipolygons absent, ways present | Implement the relation handling the tool provides |
| Build succeeds, map is blank | Layer names differ from the style | Metadata declares unexpected layer names | Align profile layer names with the style |
| Attributes inconsistent | Profile writes different types per branch | Client reports mixed attribute types | Coerce every attribute to one type in the profile |
| Very slow build | Profile does expensive work per element | Throughput far below the tool’s baseline | Move lookups out of the per-element path |
| Zoom ranges ignored | Range declared in the wrong place | Features appear outside their intended zooms | Declare ranges where the tool expects them |
Performance and Scale Jump to heading
Three things dominate a single-pass build.
The profile’s per-element cost. It runs hundreds of millions of times. A regular expression compiled inside it, a hash lookup against a large table, or anything touching the filesystem turns a two-hour build into a twelve-hour one. Precompute everything the profile needs into a small immutable structure before the run starts.
Node storage. As above: it is the constraint that decides feasibility rather than speed.
The feature store’s disk. Both tools write an intermediate feature store to disk and read it back per tile. That store is written once and read in a spatially sorted order, so sequential throughput matters more than latency, but there must be room for it — typically a multiple of the extract size.
Neither tool parallelises the profile across machines, so scaling is vertical. For very large builds that means one big machine for a few hours rather than a cluster, which is usually simpler and cheaper.
What a Profile Cannot Easily Do Jump to heading
Both tools trade flexibility for the single pass, and it is worth naming what that costs before adopting one.
It cannot look anything up. The profile sees one element at a time, with no index of what came before and no way to query a database without destroying throughput. A rule such as “render this building only if it is inside a named settlement” needs the containment computed elsewhere and attached to the element beforehand, which usually means a preprocessing pass — at which point part of the advantage of the single pass has been given back.
It cannot aggregate across features. Merging a block of adjacent buildings into one built-up polygon, as described in Merging Adjacent OSM Polygons for Low Zoom, needs all the members present at once. The tools provide limited coalescing of identical adjacent geometry at render time, but genuine cartographic aggregation is a preprocessing step.
It cannot easily be tested in isolation. A profile function depends on the host’s tag-access API, so unit-testing it means either running the tool over a small fixture extract or building a harness that fakes those functions. Running against a single-city extract is usually the pragmatic answer, and it is fast enough to sit in a change workflow.
It cannot update incrementally. A schema change means a full rebuild. That is the operational fact that makes the invalidation work in Serving & Invalidating OSM Tiles a separate concern rather than something the generator handles.
None of these is a reason to avoid single-pass tools for a base map, where the schema is stable and the input is large. They are reasons to keep thematic layers whose rules need context in a separate, GeoJSON-based pipeline, and to combine the two archives at serving time rather than forcing every layer through one tool.
Failure Modes and Gotchas Jump to heading
- The profile is code, not configuration. It deserves tests, review and a changelog, because it is where every cartographic decision lives.
- Per-element work is multiplied by hundreds of millions. Anything not constant-time in the profile is a build-time problem.
- Relations need explicit handling. A profile that only implements the node and way callbacks silently drops every multipolygon.
- Attribute types must be consistent. A branch returning a number where another returns a string produces attributes clients cannot use reliably.
- Layer names are a contract with the style. Renaming a layer in the profile silently blanks part of the map.
- Rebuilds are all-or-nothing. Neither tool updates a tile set incrementally, so a schema change means a full rebuild — which is why invalidation is handled separately.
Integration Points Jump to heading
Upstream, the input is a verified extract from OSM Extract Providers & Automated Downloads; no GeoJSON stage is involved. Downstream, the archive is served and invalidated exactly as a Tippecanoe-produced one is, per Serving & Invalidating OSM Tiles — the tools differ in how tiles are produced, not in what they produce.
The two guides below take each tool in turn: Running Planetiler on a Regional Extract and Writing a Tilemaker Lua Profile for OSM Tags.
Guides in This Topic Jump to heading
- Running Planetiler on a Regional Extract — sizing memory and disk, running the build, and reading its progress output.
- Writing a Tilemaker Lua Profile for OSM Tags — layer assignment, attributes and zoom ranges in a profile you can iterate on.
Frequently Asked Questions Jump to heading
Should I use a single-pass tool or a GeoJSON pipeline?
It depends on the size of the input and on who edits the schema. For a continent or the planet, the GeoJSON intermediate is often simply too large to materialise, and a single-pass tool is the only practical option. For a city or a small region with a schema a cartographer iterates on frequently, the GeoJSON route keeps each stage independently inspectable, which is worth a lot during development. Many teams use both: single-pass for the base map, GeoJSON for thematic overlays.
Why is my build so much slower than the tool's published numbers?
Almost always because the profile does expensive work per element. It runs once for every node, way and relation in the extract — hundreds of millions of times on a country file — so compiling a regular expression, allocating a collection or consulting a large lookup inside it multiplies that cost by the element count. Precompute everything into an immutable structure before the run and keep the per-element path to constant-time operations.
Why are my multipolygons missing?
Because the profile implements handling for nodes and ways but not for relations, which is the default state of a profile copied from a minimal example. Areas mapped as multipolygon relations — most large lakes, forests and complex buildings — arrive as relations and are silently dropped if nothing handles them. The symptom is a map that looks complete until you notice every large water body is absent.
Can these tools update an existing tile set incrementally?
Not on their own. Both are batch builders that produce a complete archive from an extract, so a change means a full rebuild. Keeping a tile set current after a diff is a separate concern handled by computing which tiles changed and re-rendering only those, which is why invalidation is treated as its own topic rather than as a feature of the generator.
How much disk does a single-pass build need?
Enough for the node store and the intermediate feature store on top of the output archive, which together are typically several times the extract size. The feature store is written once and read back in spatial order, so sequential throughput matters more than random latency. Size it before starting: both tools fail late, well into a build, when the disk fills.
Related Jump to heading
- OSM Vector Tiles & Rendering Pipelines — the parent section and the schema decisions a profile encodes.
- Building OSM Tiles with Tippecanoe — the GeoJSON-based alternative.
- Memory-Efficient Chunk Processing — the node-storage strategies both tools implement.
- Serving & Invalidating OSM Tiles — what happens to the archive afterwards.
- Understanding OSM Multipolygon Relations for GIS — the relation handling a profile must implement.
- Cartographic Generalization of OSM Data — the decisions the profile is expressing.
Up one level: OSM Vector Tiles & Rendering Pipelines.