Skills in action / Lakehouse

From open data to a governed catalog: Statbel, Databricks, BigQuery and OpenMetadata

INDEPENDENT CONSULTANT · DATA GOVERNANCE, DATA QUALITY & MDM

A working pipeline, built to show what governance looks like inside the data itself

In short

I took the open data of the Belgian statistical office (Statbel) and built, end to end, the physical layer that a data catalog needs: the files are loaded, cleaned and typed; every table and every column is described from the official dictionaries; keys are tested before they are declared; quality is measured and reported; and the result is published to BigQuery and harvested by OpenMetadata, next to a business glossary. Nothing is hidden: what the data does not say, the pipeline says it does not say.

13tables published to BigQuery
100%of the columns described
12 + 15primary and foreign keys in BigQuery
4,000+field descriptions read from about 200 Excel dictionaries
15data findings documented

This is a demonstration and training project, not a production system. It runs on Databricks Free Edition and stays within the BigQuery free tier.

Built with an AI assistant. I worked with Claude the way I would with a technical team: I wrote the conceptual specifications (the approach, the governance rules, what each layer must do), let it build the notebooks and the connector settings, and validated the quality of the result by running every step and checking it, including finding and fixing problems along the way. The documentation is written to be understood and reused, and it is part of what this example demonstrates.

Why I built it

It is the physical layer of my data catalog training: Data Owners and Data Stewards learn to link real columns to business terms. For that exercise they need a catalog that looks like the real thing, with real names, real ambiguity and real quality problems, and without confidential data. It is also the kind of foundation I put in place for clients: the same questions of ownership, definitions, keys, quality and access, answered in code that anyone can read.

The architecture

DATABRICKS FREE EDITION · UNITY CATALOGStatbel open datazip · text · GeoJSONStatbel DCAT catalogdatasets · Excel dictionariesLandingfiles unchangedBronzeas read + lineageSilvertyped · documented · keysmeta_* tablesdatasets · files · fieldsTags + quality reportdomain · personal data · run_reportCatalog explorer pagenotebook 07: one self-contained web pageBigQuery (EU)descriptions · labels · PK/FK · GEOGRAPHYOpenMetadataharvests Unity Catalog and BigQuery · business glossaryharvesteddescriptions
LayerWhat it holdsRule
LandingThe Statbel files, in a Unity Catalog volumeStored unchanged; a UTF-8 copy when the source is Windows-1252
BronzeOne Delta table per source fileData as read, all columns as text, plus _source_file, _source_url, _ingested_at
SilverTyped, documented tablesStatbel names kept; typing by column prefix; unknown markers become NULL; primary key only if tested unique
MetadataThe Statbel DCAT catalog and its field dictionaries, as tablesSource of every column description
Qualityrun_report, in Databricks and BigQueryOne row per check and per run
BigQueryThe silver tables, publishedDescriptions, labels, keys and geography; written by a service account with rights on one dataset only

Governance, built into the pipeline

PracticeHow it is done
Configuration, not codeEvery table is an entry of one configuration file (sources, filters, types, keys, dictionary). There is no table-specific code.
Documentation from the sourceDescriptions come from the Statbel dictionaries; a gap is written as a gap (Description missing in the Statbel dictionary), never hidden.
Keys that are testedA primary key is declared only if it is unique and never NULL. Foreign keys are declared after all loads. Orphan rows are counted, never dropped.
Quality reportRow counts, duplicate and NULL keys, null rates, distinct codes, values that could not be typed, values marked "not available".
LineageBronze keeps the source file, URL and load time; Delta history and Unity Catalog lineage do the rest.
Licence and attributionEvery table description ends with the Statbel licence line; labels carry source, licence, domain, period and layer.
Least privilegeNo secret in git. The BigQuery key lives in a Databricks secret scope; OpenMetadata reads through its own read-only identities.

What the data taught me

The checks found facts about the real files that a Data Steward has to know, document and decide on. None of them is a mistake of Statbel. Here are a few of the fifteen the pipeline records.

Encoding hides duplicates

Files announced as UTF-8 are Windows-1252 further down: Irène and Irêne both became Ir�ne, creating 375 false duplicate keys.

A key that is not one

The natural key of the family-name table is not unique in the source, so the pipeline refuses to declare it.

History inside the reference

Merged municipalities stay in the files with an end date: a code alone is not unique, and one decision (valid today) had to be written down.

Codes that no longer exist

Old years use municipality codes erased by mergers: thousands of orphan rows, counted and kept.

The same concept, many names

One municipality code appears under several column names, and dictionaries use other names than the files.

A prefix that lies

A column named DT_HOUR holds an hour, not a date: a type override in the configuration.

Unity Catalog or OpenMetadata?

Both, for different jobs. The glossary says what the data means and who approved it; the platform enforces who may use it. I connected both on purpose, to compare them on the same tables.

NeedOpenMetadataUnity Catalog
Business domain with an ownerDomainsNo domain object (tags)
Glossary, subject area, term, characteristicGlossaries and term hierarchy—
Definitions, synonyms, related termsYes—
Approval workflow, reviewersYes—
Link between a column and a termGlossary term on the columnOnly a free tag
Access control, column masks, row filtersDescribedEnforced
Lineage, audit, usageHarvestedNative (system tables)

What went wrong, and what I learned

The most useful part of a project like this is what does not work the first time. A selection, from the connection of the catalogs.

SymptomCauseFix
access_denied: Scopes 'all-apis' are not assignedThe OpenMetadata Unity Catalog connector needs an OAuth secret with the all APIs scopeNew secret with that scope; the identity itself stays read-only (no admin or workspace entitlement)
does not have USE SCHEMARights were granted to the wrong service principal IDCheck the identity before debugging the rights; fix the configuration and rerun the grants notebook
31 warnings "dataset not found in location US"The BigQuery connection used the US location for usage and taxonomyBoth set to EU; the missing primary and foreign keys then appeared
15 errors about the storage viewThe storage statistics view was not enabled in the Google Cloud projectEnabled once at project level (it can take up to a day to apply)
Two foreign keys refused by BigQueryBigQuery rejects self-referencing keys (the two hierarchies)Declared in Unity Catalog only: 17 foreign keys there, 15 in BigQuery
No lineage or usage from Unity CatalogFree Edition does not give access to the system tablesA known limit, kept visible instead of hidden
An HTML page instead of the fileThe Statbel server refuses clients announcing Python-urllibBrowser-like User-Agent; HTML responses are refused by the pipeline

Explore the result

The Statbel catalog explorer

Notebook 07 turns the Statbel DCAT catalog into one self-contained web page: search datasets, files, keywords and field names, filter by theme and format, and read the description of every field, with the metadata in French, Dutch, English or German. The interface of the page is in French.

Open the explorer (new tab, 1.9 MB) The business glossary built on the same data

The code

Everything is public: github.com/OlivierBouchezDataGovernance/statbel-lakehouse. Notebooks 00 to 07 run in order on a free Databricks workspace; the README and the install guide explain the Google Cloud and OpenMetadata side. Two short extracts show the style.

One table, as configuration
# config/datasets.yml: nothing else is needed to load, document and publish this table
- table: pop_structure
  domain: pop
  title: Population by municipality, nationality, marital status, age and sex
  period: "2026-01-01"
  sources:
    - url: https://statbel.fgov.be/.../TF_SOC_POP_STRUCT_2026.zip
  dictionary: https://statbel.fgov.be/.../Columns%20description.xlsx
  dictionary_aliases:           # the dictionary names the column differently
    CD_REFNIS: CD_MUNTY_REFNIS
  primary_key: [CD_REFNIS, CD_SEX, CD_NATLTY, CD_CIV_STS, CD_AGE]
  foreign_keys:
    - {column: CD_REFNIS, references: ref_municipality, referenced_column: CD_REFNIS}
Typing by column prefix
# Statbel naming convention, used as the default typing rule
CD_  code     -> string   # codes keep their leading zeros
TX_  label    -> string
MS_  measure  -> bigint, or double if decimals are found
DT_  date     -> date     # dd/MM/yyyy or yyyy-MM-dd
FL_  flag     -> boolean
LVL_ level    -> int
XY_  coord.   -> double

Limits and licence

  • It is a demonstration and training project: it runs in your own accounts, at your own risk and cost.
  • Databricks Free Edition has no system tables, so there is no automatic lineage or usage; the lineage across the two engines (Databricks to BigQuery) is not detected automatically either.
  • Statbel data: statbel.fgov.be/en/open-data, reused under CC BY 4.0. The definitions and structure are my own analysis; this work is not affiliated with Statbel.
  • Code and content: CC BY-NC 4.0, free for non-commercial use with attribution.

Let’s talk about your data

Documented, tested and measurable data is what makes a catalog useful, and what AI needs to be trustworthy. If you want the same foundations in your context, or a training for your Data Owners and Stewards, get in touch.

Contact me The data catalog training My four-phase approach