Attribute Enrichment from Authoritative Sources Jump to heading
Enrichment is the safe half of conflation: nothing is uploaded, nobody else is affected, and a mistake costs you a wrong column in your own warehouse. That safety is exactly why enrichment pipelines are built carelessly, and why the resulting datasets become impossible to reason about within a year.
The Problem This Topic Solves Jump to heading
You have OSM data and an authoritative external source that knows something the map does not — verified opening hours, an operator’s official capacity, a regulator’s licence status, a survey’s speed limits. You want your own copy of the data to carry both.
The failure scenario is a warehouse nobody trusts. External values were written into the same columns as OSM values, because that was simplest. Six months later a consumer asks whether a particular speed limit came from the map or from the reference dataset, and there is no way to tell. A second consumer wants OSM’s value because the reference is known to be stale in one region, and it is gone. The pipeline is re-run and the values change, and nobody can say whether that is because the map improved or because the matcher did.
Prerequisites Jump to heading
Have a working matcher from Matching OSM Features to External Datasets and an understanding of the licence position from Deciding if a Derived Database Triggers Share-Alike — combining OSM with an external source may produce a derived database, and the answer shapes what you may publish.
Namespace Separation Is the Whole Design Jump to heading
The single decision that determines whether an enriched dataset stays comprehensible is keeping external values in their own namespace. An external speed limit becomes ref_maxspeed, not maxspeed; an external opening-hours string becomes ref_opening_hours.
Three things follow from that, and each one is why the discipline pays.
Disagreement becomes visible. When both columns exist, a query comparing them is trivial, and the disagreement rate between OSM and an authoritative source is one of the most useful quality signals available — it finds both stale reference data and OSM features that need attention.
Precedence becomes a decision rather than an accident. With one column, whichever write happened last wins. With two, a resolved value is produced by a rule you wrote down and can change without re-running anything upstream.
Re-derivation becomes possible. Because nothing was overwritten, changing the precedence rule is a recomputation over stored columns rather than a full re-run of matching and fetching.
Precedence Rules Worth Writing Down Jump to heading
A precedence rule answers: when both sources have a value and they disagree, which one does a consumer see? Four patterns cover most cases.
Prefer OSM. Reasonable when the map is surveyed and the external source is compiled centrally. A mapper who walked the street usually knows more than a national dataset.
Prefer the external source. Reasonable when the source is genuinely authoritative for that attribute — an operator’s own record of its opening hours beats a guess from a passer-by.
Prefer the more recent. Requires both sides to carry a reliable timestamp, which OSM does at the object level but not per tag, so this is weaker than it looks.
Prefer neither; expose the disagreement. For attributes where being wrong is costly, resolving to null and flagging the conflict is more honest than picking.
The important part is that the rule is per attribute, not per dataset. An external source may be authoritative about licence status and useless about geometry.
Provenance Per Value Jump to heading
Recording where each value came from is the difference between a dataset that can answer questions and one that cannot. The minimum is, per enriched attribute: the source, the date it was fetched, and the match that connected the record to the feature.
That last part matters more than it looks. A value is only as good as the match that delivered it, so a stored match identifier lets a later review of the matcher propagate directly into a review of the values it produced. When a matching bug is found, the affected values are a query rather than an investigation.
Provenance is also what makes the licensing position defensible — the obligations in Recording OSM Data Provenance in a Pipeline apply to enriched data exactly as to raw extracts, and a per-value source record satisfies them almost incidentally.
Validation and Error Handling Jump to heading
| Condition | Root cause | Detection | Remediation |
|---|---|---|---|
| Cannot tell a value’s origin | External values written into OSM columns | Provenance query returns nothing | Separate namespaces; record source per value |
| Values change with no data change | Precedence resolved at write time | Reruns produce different outputs | Resolve at read time from stored columns |
| A stale source overrides good data | Precedence set per source, not per attribute | Disagreement concentrated in one attribute | Set precedence per attribute |
| Enrichment cannot be undone | Values written in place | No original value remains | Keep OSM values untouched; derive the resolved one |
| Bad matches silently propagate | Match identifier not stored | Affected values cannot be identified | Store the match id alongside every enriched value |
| Disagreement rate never examined | Both values present but never compared | No quality signal from the comparison | Report disagreement per attribute every run |
| Licence position unclear | Provenance absent from the output | Cannot say what is derived from what | Carry source and date through to every consumer |
When Enrichment Is the Wrong Tool Jump to heading
Three situations look like enrichment problems and are not, and recognising them saves considerable effort.
The attribute belongs in OSM. If the external source is publishable, the information genuinely improves the map, and the licence permits it, the right destination may be OpenStreetMap itself rather than your warehouse. Enrichment keeps the value private to you; contributing it makes it available to everybody and means you no longer have to maintain the join. The decision is the one framed in Preparing an OSM Import, and it is worth asking before building a permanent enrichment pipeline around a fact that could simply be mapped.
The external source is the primary dataset. Where the external data is more complete, more current and more authoritative than OSM for your purpose, enriching OSM with it has the relationship backwards. The cleaner architecture uses the external dataset as the base and attaches OSM attributes to it, which changes the matching direction, the cardinality question and what a no-match means. Nothing about the techniques changes; the framing does, and getting it wrong produces a dataset whose coverage is limited by whichever side happened to be called the base.
The disagreement is the product. Sometimes the point is not to produce a resolved value at all but to find where the two sources differ — a quality audit, a change-detection job, a survey-targeting exercise. In that case the resolved value is unnecessary and the precedence rule is a distraction; the output is the comparison itself, and treating it as an enrichment pipeline that happens to log discrepancies buries the actual deliverable in a side effect.
Measuring Enrichment Quality Jump to heading
Enrichment has a quality signal that conflation alone does not: the disagreement rate between OSM and the external source on attributes both carry.
A very low rate suggests either that the source adds little or that the matcher is matching only the easy cases. A very high rate suggests either that the source is wrong, that the matcher is wrong, or that the two are measuring different things — an external “capacity” meaning licensed occupancy and an OSM capacity meaning parking spaces, for instance.
Either way the rate is worth tracking per attribute and per region over time. A sudden change almost always means something upstream moved, and it is the cheapest available alarm on an enrichment pipeline.
Performance and Scale Jump to heading
Enrichment cost is dominated by the matching that precedes it, not by the attribute attachment. Two structural choices keep it manageable.
Store matches, not enriched rows. A match table of feature identifiers and record identifiers is small and reusable. Regenerating enriched attributes from it is a join, which is far cheaper than re-running the matcher every time a source refreshes.
Resolve at read time. Computing the resolved value in a view or at query time, rather than materialising it, means a precedence change costs nothing and never leaves stale resolved values behind.
Both point at the same architecture: store the evidence, derive the answer. The alternative — materialising everything at write time — is faster to query and impossible to correct.
Guides in This Topic Jump to heading
- Joining OSM Roads to a Speed Limit Reference — linear-referencing a road attribute onto OSM ways without losing the segmentation.
- Linking OSM Features to Wikidata Identifiers — establishing a durable identifier link that makes future enrichment nearly free.
Frequently Asked Questions Jump to heading
Why not write external values into the OSM tag columns?
Because it destroys three things at once: the ability to tell where a value came from, the ability to change the precedence rule later, and the ability to use the disagreement between the two as a quality signal. Storage is cheap and columns are free; the information you lose by collapsing them is not recoverable without re-running the whole pipeline, and sometimes not even then if the source has changed in the meantime.
Should precedence be set per source or per attribute?
Per attribute. A source can be authoritative about one thing and unreliable about another — an operator’s own record of its opening hours is better than anything a passer-by could observe, while its idea of where the building is may be a geocoded postcode. Applying one rule to a whole source guarantees that its good attributes and its bad ones are treated identically, which is exactly what you are trying to avoid.
What is the disagreement rate good for?
It is the cheapest quality alarm an enrichment pipeline has. Tracked per attribute and per region over time, a sudden change means something moved — the source refreshed with different semantics, the matcher regressed, or the map changed substantially in one area. A persistently high rate on one attribute usually means the two sides are measuring different things and the mapping needs revisiting rather than the data being wrong.
Should the resolved value be materialised or computed on read?
Computed on read, wherever query performance allows it. Materialising means every precedence change requires a rewrite and leaves the risk of stale resolved values sitting beside fresh inputs. A view or a query-time expression over the stored OSM and external columns costs a little at read time and makes the precedence rule something you can change in one place, review, and change back.
Does enrichment have licensing implications?
It can. Combining OpenStreetMap data with an external dataset in your own systems may produce what the licence calls a derived database, and what you are then permitted to publish depends on how the two are combined and what is distributed. The question is worth settling before the architecture is fixed, because a per-value provenance record — which you want anyway — is most of what a defensible answer requires.
Related Jump to heading
- OSM Conflation & Data Enrichment — the parent section and the enrichment-versus-import distinction.
- Matching OSM Features to External Datasets — producing the matches this attaches values to.
- Recording OSM Data Provenance in a Pipeline — the provenance obligations enrichment inherits.
- Deciding if a Derived Database Triggers Share-Alike — the licence question behind combining sources.
- Modelling OSM for Analytics Warehouses — where enriched features usually land.
- Validating OSM Address Tags Against a Reference — using the disagreement as a validation rule.
Up one level: OSM Conflation & Data Enrichment.