Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk5 min

How I Rebuilt OpenStreetMap’s Category Model During GSoC

Rupam Golui’s GSoC retrospective traces Nominatim’s move from one class/type pair to hierarchical category paths, and the engineering trade-offs across imports, search, indexes and API filters.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Nominatim’s old place model centered on one class/type pair, even when an OpenStreetMap object carried several useful tags. In his GSoC retrospective, contributor Rupam Golui describes replacing that limitation with hierarchical category paths attached to place records—while retaining the familiar fields for compatibility and API presentation. The change reached far beyond a database column: it affected imports, indexes, migrations, search queries, API filters, SQLite support and tests.

This is Golui’s account of the design decisions and trade-offs, including measurements from his own test environment. They are project results, not independently reproduced benchmarks or a statement about what is currently available in any particular Nominatim release. Read Golui’s original retrospective.

As an Amazon Associate I earn from qualifying purchases.

Why Nominatim needed a different category model

Nominatim geocodes OpenStreetMap data. As Golui explains, an OSM object can carry multiple main tags, but the earlier Nominatim model represented a place through a single class/type pair. That mismatch could split one multi-tag object—such as a hotel that also contains a restaurant—into multiple database rows. Administrative boundaries also needed special handling, and the model did not offer a useful hierarchical category filter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The project kept class and type for API presentation and compatibility, but made categories the basis for classification and filtering. A category is stored as a dot-separated path: for example, osm.amenity.restaurant. Because paths have a hierarchy, a filter can target a parent such as osm.amenity and include its descendants.

#1 Best Overall

How the category paths were represented

Golui’s implementation used PostgreSQL’s ltree extension and an array of paths. He says he also considered representing categories as TEXT[] and expanding prefixes, but found the path type a better fit after testing alternatives on real Nominatim data.

ltree labels have character restrictions in the supported PostgreSQL versions. The import code therefore normalizes some tag values: for instance, shop=car-repair becomes osm.shop.car_repair. If a value cannot be represented, the category uses yes; the original value remains available through other fields. This is a compatibility adaptation, not a claim that the original OSM tag itself changed.

Why one place row mattered to the import and database

The import pipeline gathered categories before inserting a place. That let it create one row for a multi-tag place rather than inserting one row per main tag and merging the rows later. A stable ordering also determined which legacy class/type pair to expose, making updates deterministic.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
1,000 Books to Read Before You Die: A Life-Changing List
  • Book - 1, 000 books to read before you die: a life-changing list (1000 before you die)
  • Language: english
  • Binding: hardcover

The category model touched multiple layers of Nominatim: import code, PostgreSQL schema, SQL ranking and trigger logic, search indexes, migrations, search paths, API parameters, SQLite adaptation and export, documentation, and tests. A mentor named Sarah asked, “Why create several rows and merge them later?” Golui describes that question as one of the prompts that helped direct the design.

What the migration involved

Golui designed the migration to work on existing databases as well as fresh imports. His final sequence added the category column, disabled the relevant trigger, backfilled categories, built indexes, re-enabled the trigger, and analyzed affected tables.

The times below are Golui’s measurements from migration experiments on his planet database in 2026. They describe that particular setup, not a general estimate for another database.

Migration approach Reported time
Indexes created before the bulk update, with triggers enabled About 63 minutes
Backfill before index creation About 47 minutes
Temporary-table approach About 1 hour 40 minutes
Final described sequence About 42 minutes

Search speed and storage: a trade-off, not a universal win

The project replaced POI and near-search paths that used many place_classtype_* tables with category filtering on placex. That simplified the table layout, but the first categories-only query path could build a bitmap for a very large set of matching places before applying the spatial filter. Golui gives about 1.8 million matching restaurant rows as an example of the scale behind that problem.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The figures below are comparisons reported by Golui in 2026. The categories-only path with the old index was substantially slower in his examples; combining a GiST index on centroid and categories with centroid-based filtering narrowed the gap. These timings depend on the author’s data and test conditions and should not be read as general latency expectations.

Query Master Category path, old index Combined index
POI About 0.69 ms About 106.5 ms About 1.28 ms
Near search About 22.6 ms About 510 ms About 75 ms

In another example, Golui reports an old specialized POI path at about 8 ms, compared with about 655 ms warm and 2,617 ms cold for the first new path. He notes that some queries remained slower than with specialized tables even after the index improvement. In exchange, his estimate was that the change removed 428 tables and about 8.2 GB of separate table and index storage.

How the search API’s category filters work

The project added include and exclude category parameters to /search. The examples below show the intended syntax and distinctions in grouping; Golui’s article provides the accompanying examples for selecting descendants, combining categories, and excluding fast food.

  • include=osm.amenity selects that category and its descendants, allowing a request for anything under osm.amenity.
  • Comma-separated values within one parameter and repeated parameters have different AND/OR behavior. Do not treat the two forms as interchangeable when constructing a filter.
  • Exclusion follows the inverse grouping logic, so the way exclusions are combined also depends on whether values are comma-separated or repeated.

For example, a reader looking for restaurants in Berlin while excluding osm.amenity.fast_food should follow the exact include/exclude form shown in the original API examples, rather than infer grouping from the parameter names alone. Data sources without categories, including postcodes and interpolations, cannot satisfy an include filter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What testing revealed—and what it did not

For a full-planet geocoder-tester comparison, Golui reports the same counts on master and PR #4146: 7,919 failed, 11,113 passed, and 3,264 skipped. These are the author’s reported test results, not an independently audited comparison.

He also recounts two debugging traps. An apparent speedup in an earlier comparison came from cache order. Later, airport regressions were initially attributed to the category change, but replication catch-up had left about 4.5 million rows at indexed_status = 2; because indexing was incomplete, those rows were unsearchable. The episode illustrates why test state and data readiness matter when interpreting a performance or result change.

What the project says about changing a mature system

Golui says the project was complete according to its scope plan and did not require a follow-up task to use the feature. He describes richer categories—for example, cuisine.italian or access.wheelchair.yes—as possible future expansion if clearer use cases emerge. That is a direction he identifies, not confirmation of current release availability.

His broader lesson is that a data-model change in a production-oriented geocoder cannot stop at the schema. It has to be followed through application code, database functions, query indexes, migration behavior, API paths, SQLite compatibility and tests. Golui writes: “The technical result is a category system, but the more useful outcome for me was learning how to make a cross-cutting change in a production-oriented open-source codebase.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

Bestseller No. 1
SaleBestseller No. 2
1,000 Books to Read Before You Die: A Life-Changing List
1,000 Books to Read Before You Die: A Life-Changing List
Book - 1, 000 books to read before you die: a life-changing list (1000 before you die); Language: english
$19.37

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.