Imagine correcting a bend in an OpenStreetMap road by moving one point. The road still refers to the same points in the same order, yet its shape has changed. Software importing the edit must discover that consequence. In osm2pgsql, the component called the “middle” retains the relationships needed to rebuild the affected road. Following that small correction explains why an updateable map database needs more than its finished geometry.[2][3]
Osm2pgsql is an open-source importer for PostgreSQL with the PostGIS spatial extension. It converts OSM data into tables for rendering and other uses.[1] This account follows its version 2 architecture and flex output, with replication behavior checked against the 2.3.1 command manual.[4][5]
A road can change without a new road record
OSM stores a node's latitude and longitude on the node. A way contains an ordered sequence of node references; tags describe what that way represents. Relations assemble elements into larger structures, including multipolygons and routes.[2] These distinctions are easy to overlook when a screen presents everything as lines and labels.
Consider a deliberately small example: way 900 follows nodes 10, 11, and 12. Moving node 11 changes the line through those coordinates without changing the way's reference list. An importer that only replaces records explicitly modified upstream would miss the road's new shape. The example exposes a dependency: the way's geometry depends on information stored elsewhere.
Developer Jochen Topf's explanation of the middle makes this responsibility explicit. It retains node locations and way membership, allowing geometry to be assembled and changes to propagate to ways that use a changed node. It also preserves the ingredients needed to construct relation geometries.[3] That retained structure gives the importer a route back from a finished line to the objects that determine it.
The same distinction separates two workloads. For a disposable import, intermediate information need survive only the run. For an initial import followed by updates, it must survive between runs.[3] A database can therefore be perfectly useful for querying today while lacking the state needed to absorb tomorrow's edits.
Lua decides what the application receives
The middle supplies the ingredients; flex output defines the application tables. A Lua configuration can use osm2pgsql.define_way_table() to declare a table, inspect tags in osm2pgsql.process_way(object), and obtain geometry with object:as_linestring().[4]
For a road layer, the configuration might select ways carrying highway, then retain a name, road class, and geometry. This is an illustrative schema choice. A street-label renderer and a road-maintenance analysis need not ask for identical columns.
Object IDs connect those output rows to their OSM origins. Osm2pgsql uses that connection to remove or replace derived rows when an object changes or disappears; modifications are processed as deletion followed by recreation.[4] Rebuilding a road consequently means revisiting both its geometry and the rules that selected its output.
There is a storage consequence. The v2 manual requires --slim for later updates. Adding --drop removes the persistent middle tables after import and prevents that workflow.[4] For a team choosing between periodic rebuilds and continuous updates, retained intermediate data is part of the operating cost.
The next edit needs a known starting point
Dependency tracking answers which geometry must change. Replication state answers which changes have arrived. The companion osm2pgsql-replication tool exposes init, update, and status: establish a starting point, apply subsequent changes, and inspect progress. Its state is stored in the database.[5]
The independent Switch2OSM guide adds useful deployment context: regional extracts can have matching update services, including Geofabrik's daily feeds.[6] Choosing an update source belongs alongside choosing the initial extract. An operator should be able to identify both before diagnosing a missing edit.
The replication tool downloads bounded chunks and invokes osm2pgsql to apply them. status --json exposes local and upstream sequence information and timestamps.[5] For a small team already comfortable operating PostgreSQL, those values offer a practical freshness check. A successful scheduled process alone tells less: it may be following a service whose newest data is older than the reader expects.
The database is only one stop
The corrected geometry still has to reach the map image. Switch2OSM's example passes an expiry list to render_expired, which can trigger rerendering, mark tiles dirty, or delete them.[6] Its deployment instructions provide an external check on the architecture: importing data and refreshing cached tiles are separate pieces of work.
There is a revealing failure case in the replication manual. A --post-processing script runs after osm2pgsql succeeds. If that script fails, the overall update fails and replication progress is not advanced; another attempt downloads and reapplies the changes.[5] Database work may therefore have happened even though the complete update has not succeeded. An operator's post-processing script should tolerate being run again.
This suggests a focused rehearsal for a team running its own tile service. In a local fixture, move a node used by a road, apply the change, and inspect the resulting line. Then check the expiry work and the tile actually served. Keep the experiment local; no public map edit is needed. Each observation answers a different question: did the dependency propagate, did rendering notice, and did the reader receive the replacement?
The appeal of this architecture becomes visible at that ordinary bend in the road. A contributor makes a small correction. Retained relationships, output rules, update progress, and rendering work give an operator places to follow it. When the map remains wrong, those separate stages make the fault easier to locate.
Sources
- osm2pgsql project repository, README—open-source importer scope and PostgreSQL/PostGIS integration.
- OpenStreetMap Wiki, “Elements”—nodes, way references, tags, and relations.
- Jochen Topf, “Osm2pgsql Middle Improvements,” December 21, 2020—developer explanation of retained objects, geometry dependencies, and import versus update lifetimes.
- osm2pgsql v2 Manual, “Flex Output” and “Middle”—Lua callbacks, geometry construction, output IDs, and persistent storage requirements.
- osm2pgsql-replication command manual, version 2.3.1—initialization, bounded updates, status reporting, and post-processing failure behavior.
- Switch2OSM, “Updating your database as people edit OpenStreetMap using osm2pgsql”—independent integration guide covering regional update services and tile expiry.
- contrapunctus, “Organizing OpenStreetMap mapping parties”—organizer's account and photograph captioned as an indoor iD workshop at SFLC.in.