UC_MD

•

MDM HUB

Source of Truth on Unity Catalog

People · Finance · Manufacturing

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Implementation Architecture & Operating Guide

Version 1.0  |  Confidential

1. Situation & Design Decisions

1.1 Current State

The organisation has three domain-specific Gold catalogs already running on the same Databricks workspace / metastore. Each catalog holds curated, high-quality data for its domain but operates in isolation with no shared entity keys across domains.

DomainExisting CatalogKey EntitiesKey Problem
Peoplepeople_goldEmployee, Department, Role, PositionEmployee IDs local to HR system — no link to Finance cost centres or Manufacturing plants
Financefinance_goldCost Centre, GL Account, Budget, Vendor, Legal EntityVendor and employee records exist independently with no shared identifier
Manufacturingmanufacturing_goldPlant, Asset, Work Order, BOM, Production RunPlant codes and responsible persons not linked to People or Finance domains

1.2 Target State

A new Unity Catalog — mdm_hub — is created in the same Databricks metastore. It acts as the Single Source of Truth (SSoT) by:

  • Pulling from all three existing Gold catalogs via live views (no data duplication).
  • Running entity matching to generate a Global Entity Index (GEI) that assigns a stable mdm_id across domains.
  • Publishing certified Golden Record tables that all Databricks workloads query instead of going to domain catalogs directly.
  • Registering all assets in Azure Purview for lineage, classification, and stewardship.

1.3 Key Design Decisions

DecisionChoiceRationale
Hub locationNew Unity Catalog: mdm_hubClean separation — domain catalogs stay unchanged; Hub is additive only
Data movementViews over domain Gold tables (no ETL copy)Zero duplication, always current, reduces storage cost
Entity matchingDeterministic first, probabilistic fallbackNo shared keys exist; matching engine generates mdm_id
Key strategySurrogate mdm_id (UUID) as global keyDomain keys preserved as source_id columns; mdm_id is the new universal identifier
Consuming patternDirect catalog reference mdm_hub.golden.*Downstream notebooks / jobs switch catalog reference — no API layer needed initially
GovernanceAzure Purview scans mdm_hub; Purview owns lineage + classificationPurview tracks Bronze→Gold→Hub lineage end-to-end

2. MDM Hub Architecture

2.1 Catalog & Schema Structure

The mdm_hub catalog is organised into four schemas, each serving a distinct layer of the hub:

SchemaFull PathPurposeAccess
source_viewsmdm_hub.source_views.*Live views pointing to domain Gold tables — read-only projections, no transformationMDM Engineers (read), Matching jobs (read)
matchingmdm_hub.matching.*Entity matching output — candidate pairs, match scores, manual review queueMDM Engineers (write), Stewards (review)
goldenmdm_hub.golden.*Certified Golden Record tables — the single source of truth for all consuming workloadsAll Databricks principals (read)
auditmdm_hub.audit.*Change history, match decision log, DQ metrics, steward actionsDGO, Stewards, Compliance (read)

2.2 Data Flow

Data flows through four stages from domain catalogs to consuming workloads:

StageFrom → ToMechanismFrequency
1 — Projectpeople_gold / finance_gold / manufacturing_gold → mdm_hub.source_viewsUnity Catalog Views (CREATE VIEW … AS SELECT …)Real-time (live views)
2 — Matchmdm_hub.source_views → mdm_hub.matchingDatabricks notebook / DLT matching pipeline (blocking + scoring)Daily batch or triggered on Gold update
3 — Certifymdm_hub.matching (approved pairs) → mdm_hub.goldenMERGE INTO golden records; steward sign-off gateDaily after matching run
4 — Consumemdm_hub.golden → downstream notebooks, dashboards, jobsStandard Unity Catalog SELECT; switch catalog in connection stringOn-demand / streaming

2.3 Golden Record Entity Model

Each domain contributes specific entities to the Hub. The matching engine links them using a shared mdm_id:

Hub EntitySource: PeopleSource: FinanceSource: ManufacturingLink Logic
Person (Golden)employee_id, name, email, department, rolecost_centre_owner_id, vendor_contactplant_manager_id, asset_owner_idMatch on: name + email (deterministic); name + phone (probabilistic)
Organisational Unitdepartment_code, dept_namecost_centre_code, legal_entityplant_code, plant_nameMatch on: dept_code ↔ cost_centre_code mapping table + name fuzzy
Location(office location if present)legal_entity addressplant address, geo coordinatesMatch on: address normalisation + geo distance threshold
Vendor / Supplier(not present)vendor_id, vendor_name, tax_id(not present)Single source — dedup within Finance only

3. Entity Matching Design

Since no shared key exists across domain catalogs, a two-phase matching engine is required to generate the global mdm_id.

3.1 Matching Phases

PhaseMethodWhen UsedOutput
Phase 1 — DeterministicExact match on email, tax_id, or known mapping table (dept_code ↔ cost_centre)Where at least one reliable shared attribute existsHigh-confidence match pairs (score = 1.0)
Phase 2 — ProbabilisticJaro-Winkler name similarity + phonetic + address normalisation (via Databricks + difflib / Zingg OSS)Remaining unmatched records after Phase 1Scored candidate pairs (threshold ≥ 0.85 auto-approve, 0.70–0.85 manual review)
Phase 3 — Manual ReviewSteward reviews low-confidence pairs in review UI (Purview / custom notebook widget)Pairs scoring 0.70–0.85Steward approve / reject → written to matching.review_decisions

3.2 Match Score Thresholds

Score RangeDecisionActionAudit Trail
≥ 0.90Auto-Approve — High ConfidenceMERGE into mdm_hub.golden immediatelyWritten to audit.match_log with auto_approved=true
0.75 – 0.89Manual Review RequiredHeld in matching.review_queue; steward action requiredWritten to audit.review_queue; SLA 48 hours
< 0.75No Match — RejectRecords remain as standalone entities in their domainWritten to audit.match_log with rejected=true

3.3 Matching Pipeline Code (Databricks DLT)

The matching pipeline is implemented as a Databricks Delta Live Tables pipeline. Key stages:

# mdm_matching_pipeline.py  — DLT pipeline for Person entity matching

import dlt

from pyspark.sql import functions as F

from pyspark.sql.functions import col, udf, levenshtein, soundex

from pyspark.sql.types import FloatType

# ── STAGE 1: Source projections (already in source_views, referenced here) ──

@dlt.table(name=’people_candidates’, schema=’mdm_hub.matching’)

def people_candidates():

    return spark.read.table(‘mdm_hub.source_views.vw_people_person’) \

           .select(’employee_id’,’full_name’,’email’,’phone’,’dept_code’) \

           .withColumn(‘source’, F.lit(‘people’))

@dlt.table(name=’finance_candidates’, schema=’mdm_hub.matching’)

def finance_candidates():

    return spark.read.table(‘mdm_hub.source_views.vw_finance_vendor_contact’) \

           .select(‘contact_id’,’full_name’,’email’,’phone’,’cost_centre’) \

           .withColumn(‘source’, F.lit(‘finance’))

# ── STAGE 2: Blocking (reduce comparison space) ──

# Block on first 3 chars of surname + soundex of email domain

@dlt.table(name=’match_candidates_blocked’)

def blocked():

    p = dlt.read(‘people_candidates’).withColumn(‘block_key’,

            F.concat(F.substring(‘full_name’, 1, 3), soundex(’email’)))

    f = dlt.read(‘finance_candidates’).withColumn(‘block_key’,

            F.concat(F.substring(‘full_name’, 1, 3), soundex(’email’)))

    return p.join(f, ‘block_key’, ‘inner’) \

            .filter(col(‘p.source’) != col(‘f.source’))

# ── STAGE 3: Score pairs ──

@udf(FloatType())

def jaro_winkler(s1, s2):

    # install jellyfish on cluster: pip install jellyfish

    import jellyfish

    return float(jellyfish.jaro_winkler_similarity(s1 or ”, s2 or ”))

@dlt.table(name=’scored_pairs’)

def scored_pairs():

    blocked = dlt.read(‘match_candidates_blocked’)

    return blocked.withColumn(‘name_score’, jaro_winkler(‘p.full_name’,’f.full_name’)) \

                  .withColumn(’email_exact’, (col(‘p.email’) == col(‘f.email’)).cast(‘float’)) \

                  .withColumn(‘final_score’,

                      col(’email_exact’) * 0.6 + col(‘name_score’) * 0.4)

# ── STAGE 4: Route by threshold ──

@dlt.table(name=’auto_approved_pairs’)

@dlt.expect_or_drop(‘high_confidence’, ‘final_score >= 0.90’)

def auto_approved():

    return dlt.read(‘scored_pairs’).filter(col(‘final_score’) >= 0.90)

@dlt.table(name=’review_queue’)

def review_queue():

    return dlt.read(‘scored_pairs’) \

              .filter((col(‘final_score’) >= 0.75) & (col(‘final_score’) < 0.90)) \

              .withColumn(‘review_status’, F.lit(‘PENDING’)) \

              .withColumn(‘assigned_steward’, F.lit(None))

3.4 Golden Record MERGE Logic

After matching, the golden record is created or updated using a MERGE statement. The mdm_id is a UUID generated on first creation and preserved on subsequent updates.

— mdm_hub.golden.person — MERGE from approved pairs

MERGE INTO mdm_hub.golden.person AS target

USING (

  SELECT

    COALESCE(existing.mdm_id, uuid()) AS mdm_id,

    p.employee_id     AS people_source_id,

    f.contact_id      AS finance_source_id,

    COALESCE(p.full_name, f.full_name)  AS canonical_name,

    COALESCE(p.email,    f.email)       AS canonical_email,

    COALESCE(p.phone,    f.phone)       AS canonical_phone,

    p.dept_code       AS people_dept_code,

    f.cost_centre     AS finance_cost_centre,

    current_timestamp()                 AS last_updated,

    ‘AUTO_MATCH’                        AS update_source

  FROM mdm_hub.matching.auto_approved_pairs ap

  JOIN mdm_hub.source_views.vw_people_person  p ON ap.people_id  = p.employee_id

  JOIN mdm_hub.source_views.vw_finance_vendor_contact f ON ap.finance_id = f.contact_id

  LEFT JOIN mdm_hub.golden.person existing

         ON existing.people_source_id = p.employee_id

) AS source

ON target.people_source_id = source.people_source_id

   OR target.finance_source_id = source.finance_source_id

WHEN MATCHED THEN UPDATE SET

    target.finance_source_id = source.finance_source_id,

    target.canonical_email   = source.canonical_email,

    target.last_updated      = source.last_updated

WHEN NOT MATCHED THEN INSERT *;

4. mdm_hub Catalog — Full Implementation

4.1 Catalog Setup (Databricks SQL)

— Step 1: Create the hub catalog

CREATE CATALOG IF NOT EXISTS mdm_hub

  COMMENT ‘Master Data Management Hub — Single Source of Truth’;

— Step 2: Create schemas

CREATE SCHEMA IF NOT EXISTS mdm_hub.source_views COMMENT ‘Live views over domain Gold catalogs’;

CREATE SCHEMA IF NOT EXISTS mdm_hub.matching      COMMENT ‘Entity matching staging and review’;

CREATE SCHEMA IF NOT EXISTS mdm_hub.golden        COMMENT ‘Certified Golden Records’;

CREATE SCHEMA IF NOT EXISTS mdm_hub.audit         COMMENT ‘Change history, DQ metrics, steward log’;

— Step 3: Grant read access on Golden layer to all domain principals

GRANT USE CATALOG ON CATALOG mdm_hub TO `data-consumers`;

GRANT USE SCHEMA  ON SCHEMA mdm_hub.golden TO `data-consumers`;

GRANT SELECT      ON ALL TABLES IN SCHEMA mdm_hub.golden TO `data-consumers`;

— Step 4: Restrict matching + audit to MDM engineers and stewards only

GRANT USE SCHEMA ON SCHEMA mdm_hub.matching TO `mdm-engineers`;

GRANT USE SCHEMA ON SCHEMA mdm_hub.audit    TO `mdm-engineers`, `data-stewards`;

4.2 Source Views — Domain Projections

Views in mdm_hub.source_views are thin projections — they rename columns to a canonical standard and drop domain-internal fields that are not needed in the hub.

— People domain view

CREATE OR REPLACE VIEW mdm_hub.source_views.vw_people_person AS

SELECT

    employee_id                          AS source_id,

    CONCAT(first_name, ‘ ‘, last_name)   AS full_name,

    LOWER(TRIM(work_email))              AS email,

    mobile_number                        AS phone,

    department_code                      AS dept_code,

    job_title                            AS role,

    employment_status,

    ‘people_gold’                        AS source_catalog,

    _updated_at                          AS source_updated_at

FROM people_gold.hr.employees

WHERE employment_status = ‘ACTIVE’;

— Finance domain view

CREATE OR REPLACE VIEW mdm_hub.source_views.vw_finance_cost_centre AS

SELECT

    cost_centre_code                     AS source_id,

    cost_centre_name,

    legal_entity_code,

    owner_employee_ref                   AS finance_owner_ref,  — link candidate to People

    gl_account_group,

    ‘finance_gold’                       AS source_catalog,

    _updated_at                          AS source_updated_at

FROM finance_gold.gl.cost_centres

WHERE active_flag = 1;

— Manufacturing domain view

CREATE OR REPLACE VIEW mdm_hub.source_views.vw_manufacturing_plant AS

SELECT

    plant_code                           AS source_id,

    plant_name,

    plant_manager_employee_ref,          — link candidate to People

    site_address,

    region_code,

    ‘manufacturing_gold’                 AS source_catalog,

    _updated_at                          AS source_updated_at

FROM manufacturing_gold.operations.plants

WHERE operational_status = ‘ACTIVE’;

4.3 Golden Record Table DDL

— PERSON — core cross-domain entity

CREATE TABLE IF NOT EXISTS mdm_hub.golden.person (

    mdm_id               STRING    NOT NULL COMMENT ‘Global surrogate key — stable UUID’,

    people_source_id     STRING    COMMENT ’employee_id from people_gold’,

    finance_source_id    STRING    COMMENT ‘contact_id from finance_gold’,

    mfg_source_id        STRING    COMMENT ‘manager ref from manufacturing_gold’,

    canonical_name       STRING    NOT NULL,

    canonical_email      STRING,

    canonical_phone      STRING,

    dept_code            STRING    COMMENT ‘From People domain’,

    cost_centre_code     STRING    COMMENT ‘From Finance domain’,

    plant_code           STRING    COMMENT ‘From Manufacturing domain’,

    match_confidence     FLOAT     COMMENT ‘Score from matching engine’,

    certification_status STRING    DEFAULT ‘CERTIFIED’,

    certified_by         STRING,

    certified_at         TIMESTAMP,

    last_updated         TIMESTAMP,

    PRIMARY KEY (mdm_id) NOT ENFORCED

) USING DELTA

TBLPROPERTIES (

    ‘delta.enableChangeDataFeed’ = ‘true’,

    ‘quality’ = ‘gold’,

    ‘domain’  = ‘cross-domain’,

    ‘owner’   = ‘mdm-team’

);

— ORGANISATIONAL UNIT

CREATE TABLE IF NOT EXISTS mdm_hub.golden.org_unit (

    mdm_id               STRING    NOT NULL,

    people_dept_code     STRING,

    finance_cost_centre  STRING,

    mfg_plant_code       STRING,

    canonical_name       STRING    NOT NULL,

    legal_entity_code    STRING,

    region_code          STRING,

    head_person_mdm_id   STRING    COMMENT ‘FK to mdm_hub.golden.person’,

    match_confidence     FLOAT,

    last_updated         TIMESTAMP,

    PRIMARY KEY (mdm_id) NOT ENFORCED,

    FOREIGN KEY (head_person_mdm_id) REFERENCES mdm_hub.golden.person(mdm_id) NOT ENFORCED

) USING DELTA;

— LOCATION

CREATE TABLE IF NOT EXISTS mdm_hub.golden.location (

    mdm_id               STRING    NOT NULL,

    mfg_plant_code       STRING,

    finance_entity_addr  STRING,

    canonical_address    STRING,

    region_code          STRING,

    country_code         STRING,

    geo_lat              DOUBLE,

    geo_lng              DOUBLE,

    org_unit_mdm_id      STRING,

    last_updated         TIMESTAMP,

    PRIMARY KEY (mdm_id) NOT ENFORCED

) USING DELTA;

5. Azure Purview Integration

5.1 Purview Registration & Scanning

StepActionDetail
1Register Databricks source in PurviewPurview → Data Map → Register → Azure Databricks. Point to the workspace. Purview authenticates via managed identity.
2Create Scan targeting mdm_hub catalogScan filter: catalog = mdm_hub, schemas = source_views, matching, golden, audit. Schedule: daily.
3Apply Classification RulesCreate custom classification rules in Purview for: MDM_GOLDEN_RECORD (tag all tables in golden.*), PII (email, phone, name columns), CROSS_DOMAIN_KEY (mdm_id column).
4Configure Business GlossaryCreate terms in Purview Glossary: Golden Record, mdm_id, Source of Truth, Match Confidence, Domain Catalog. Link terms to mdm_hub.golden.* table columns.
5Lineage wiringPurview auto-captures Unity Catalog lineage. Manually register the DLT matching pipeline as a lineage process: source_views → matching → golden.
6Data Policy (optional)Create Purview Data Access Policy to allow data-consumers group SELECT on mdm_hub.golden.* — pushed back to Unity Catalog via policy sync.

5.2 Lineage Map (Purview)

End-to-end lineage visible in Azure Purview after setup:

Lineage NodeTypeCatalog / SystemConnected To
people_gold.hr.employeesSource Tablepeople_gold (Databricks)mdm_hub.source_views.vw_people_person
finance_gold.gl.cost_centresSource Tablefinance_gold (Databricks)mdm_hub.source_views.vw_finance_cost_centre
manufacturing_gold.operations.plantsSource Tablemanufacturing_gold (Databricks)mdm_hub.source_views.vw_manufacturing_plant
DLT Matching PipelineProcess / ETLDatabricks DLTsource_views → matching.scored_pairs
mdm_hub.matching.auto_approved_pairsIntermediate Tablemdm_hub (Databricks)golden.person (via MERGE job)
mdm_hub.golden.personGolden Record Tablemdm_hub (Databricks)All downstream consuming notebooks/jobs
mdm_hub.golden.org_unitGolden Record Tablemdm_hub (Databricks)All downstream consuming notebooks/jobs

6. Data Governance Framework for the Hub

6.1 Governance Principles (Hub-Specific)

PrincipleWhat It Means for mdm_hub
Domain catalogs are read-only inputsmdm_hub never writes back to people_gold, finance_gold, or manufacturing_gold. Data flows one direction only: domain → hub.
mdm_id is immutable once assignedA golden record’s mdm_id never changes. If a merge decision is reversed, the record is marked RETIRED — not deleted.
Match decisions are auditableEvery match approval (auto or manual) is written to mdm_hub.audit.match_log with timestamp, steward ID, and score.
Golden = CertifiedA record in mdm_hub.golden.* is certified by definition. Uncertified records live in matching.review_queue only.
No consumer touches matching or audit schemasOnly MDM engineers and stewards access matching.* and audit.*. Consumers only see golden.*.

6.2 Data Quality Gates

Records are blocked from promotion to golden.* unless they pass all quality gates in the DLT pipeline:

GateRuleThresholdAction on Failure
Completenesscanonical_name must not be null100%Record dropped — written to matching.rejected
Email validitycanonical_email must match regex ^[\w.-]+@[\w.-]+\.[a-z]{2,}$Soft checkFlag set; record still promoted but tagged EMAIL_SUSPECT
Match scoreauto-approval requires final_score ≥ 0.9090%Routed to review_queue if 0.75–0.89; rejected if < 0.75
Duplicate checkNo two golden records may share the same canonical_email0 duplicatesSecond record flagged DUPLICATE_SUSPECT; steward review
Cross-domain linkAt least 2 source_ids populated for entity to be ‘cross-domain certified’≥ 2 sourcesSingle-source records marked SINGLE_SOURCE (valid but not cross-domain)

6.3 Governance Structure

RoleResponsibility in Hub ContextCatalog Access
MDM Hub Owner (1)Accountable for mdm_hub catalog; approves architecture changes; chairs MDM Working GroupMetastore admin on mdm_hub
Domain Data Steward — People (1)Reviews person match queue; approves/rejects low-confidence pairs involving People recordsmdm_hub.matching + mdm_hub.audit (read/write review_queue)
Domain Data Steward — Finance (1)Reviews cost centre and org unit matches involving Finance recordsmdm_hub.matching + mdm_hub.audit (read/write review_queue)
Domain Data Steward — Manufacturing (1)Reviews plant and location matches involving Manufacturing recordsmdm_hub.matching + mdm_hub.audit (read/write review_queue)
MDM Engineer (2)Maintains DLT pipelines, matching rules, golden DDL, Purview connectorFull access to mdm_hub (all schemas)
Data ConsumerReads from mdm_hub.golden.* for analytics, reporting, downstream jobsmdm_hub.golden.* SELECT only

7. Target Operating Model

7.1 Daily Operating Rhythm

TimeActivityTriggerOwner
00:00 – 02:00Domain Gold tables refreshed by existing domain pipelinesScheduled domain jobsDomain Engineers
02:00 – 04:00DLT matching pipeline runs: source_views → matching.*Databricks workflow scheduleMDM Engineer (automated)
04:00 – 06:00Auto-approved pairs MERGED into golden.*Post-matching workflow triggerMDM Engineer (automated)
08:00Stewards notified of new review_queue items via email alertDatabricks SQL alert on review_queue countMDM Engineer (automated alert)
08:00 – 12:00Stewards process review queue; approve/reject pairsSteward manual action in Purview / notebook UIDomain Stewards
12:00Steward-approved pairs MERGED into golden.* (second daily run)Post-review workflow triggerMDM Engineer (automated)
18:00Azure Purview incremental scan on mdm_hubPurview scheduled scanPurview (automated)
23:00DQ metrics computed; alerts sent if golden.* thresholds breachedDatabricks SQL alertMDM Engineer (automated)

7.2 Engagement Model

TeamHow They Engage with the HubChannel
People / HR TeamSteward reviews person match queue; approves merges; raises data issues via Jira MDM boardPurview Stewardship portal + Jira
Finance TeamSteward reviews cost centre / org unit matches; validates canonical legal entity namesPurview + Databricks SQL notebook
Manufacturing TeamSteward reviews plant / location matches; validates plant manager linksPurview + Databricks SQL notebook
BI / Analytics ConsumersSwitch Databricks SQL catalog reference from domain catalog to mdm_hub.golden — query golden records directlyDatabricks SQL / notebook
Data Engineering (downstream)Jobs reference mdm_hub.golden.person.mdm_id as foreign key for cross-domain joinsUnity Catalog table reference
Platform / DevOpsCI/CD deploys matching rule changes via Databricks Asset Bundles (DAB); no manual cluster changesGitHub Actions + DAB

7.3 Change Control

  • Changes to matching rules (score weights, blocking keys) require a pull request reviewed by MDM Hub Owner and at least one Domain Steward.
  • Schema changes to mdm_hub.golden.* require impact assessment (check downstream notebook dependencies via Purview lineage) and a 2-week notice to consumers.
  • New domain onboarding (e.g. adding a Procurement catalog) follows a 6-week intake process: source view → matching config → golden DDL → steward assignment → go-live.

8. RACI Matrix

R = Responsible  |  A = Accountable  |  C = Consulted  |  I = Informed

8.1 MDM Hub Activities

ActivityMDM Hub OwnerPeople StewardFinance StewardMfg StewardMDM EngineerConsumerDGO
Design mdm_hub catalog structureACCCRIC
Create/maintain source_viewsCCCCR/AII
Design matching rules (Person)ARCICIC
Design matching rules (Org Unit)ACRCCIC
Design matching rules (Location)AICRCIC
Build DLT matching pipelineCIIIR/AII
Review match queue — PersonIR/AIIIII
Review match queue — Org UnitICR/ACIII
Review match queue — LocationIICR/AIII
Certify Golden RecordsACCCRIC
Grant consumer access to golden.*AIIIRIC
Monitor DQ metrics dailyIIIIR/AII
Resolve match pipeline failures (P1)AIIIRII
Purview scan & lineage configCIIIR/AIC
Quarterly access reviewACCCRIC
Onboard new domain to hubACCCRIC
Retire / archive golden recordACCCRIC
Report Hub KPIs to leadershipR/ACCCCIC

9. Hub KPIs & Monitoring

KPITargetFrequencySourceOwner
Golden Record Coverage — Person≥ 95% of active employees matched across ≥ 2 domainsWeeklymdm_hub.audit.match_logPeople Steward
Golden Record Coverage — Org Unit≥ 90% of dept codes linked to cost centresWeeklymdm_hub.golden.org_unitFinance Steward
Auto-approval Rate≥ 80% of candidate pairs auto-approved (score ≥ 0.90)Dailymdm_hub.matching.scored_pairsMDM Engineer
Review Queue SLA0 items in review_queue older than 48 hoursDailymdm_hub.matching.review_queueMDM Hub Owner
Golden Record Completenesscanonical_name populated: 100%; canonical_email: ≥ 95%Dailymdm_hub.golden.personMDM Engineer
Duplicate Golden Records0 duplicates in golden.* (same email, different mdm_id)DailyDQ check job on golden.*MDM Engineer
Purview Lineage Coverage100% of golden.* tables have end-to-end lineage in PurviewMonthlyAzure Purview InsightsDGO
Consumer Adoption≥ 80% of cross-domain notebooks referencing mdm_hub.golden.* (not domain catalogs)MonthlyUnity Catalog query audit logMDM Hub Owner

10. Implementation Plan

WeekActivityDeliverableOwner
Week 1–2Create mdm_hub catalog; all 4 schemas; RBAC grants; register in Azure Purviewmdm_hub catalog live; Purview scan runningMDM Engineer
Week 2–3Build source_views for all 3 domain catalogs; validate column mapping with stewards9 source views live; steward sign-off on canonical column namesMDM Engineer + Stewards
Week 3–5Build DLT matching pipeline for Person entity; unit test with sample data in sandboxMatching pipeline in staging; scored_pairs table populatedMDM Engineer
Week 5–6Stewards define match rule thresholds; configure review_queue alertsThreshold config agreed; alert triggers testedStewards + MDM Engineer
Week 6–7First full matching run on Person; stewards clear review queue; first golden.person loadgolden.person table with first certified recordsMDM Engineer + People Steward
Week 7–9Extend matching to Org Unit; build golden.org_unit; link to golden.person via head_person_mdm_idgolden.org_unit live; cross-domain links establishedMDM Engineer + Finance + Mfg Stewards
Week 9–10Build golden.location; wire full Purview lineage; configure DQ monitoring jobsAll 3 golden tables live; Purview lineage end-to-end; DQ dashboard in Power BIMDM Engineer
Week 10–11Consumer onboarding — update downstream notebooks to reference mdm_hub.golden.*Consuming jobs switched; adoption metric baseline setMDM Engineer + consumers
Week 11–12Hypercare — daily steward + engineer review; KPI baselining; documentation handoffHub in steady-state operations; runbook completeMDM Hub Owner

10.1 Critical Dependencies

  • Domain Gold tables must have stable, documented schemas before source_views are built. Any upstream schema change breaks the view.
  • At least one reliable overlap attribute (email, employee_ref column in Finance and Manufacturing) must exist for deterministic matching to work. Validate with stewards in Week 2.
  • Azure Purview Databricks connector requires the workspace to be on Unity Catalog (not legacy Hive metastore). Confirm metastore type before Week 1.
  • Stewards from all three domains must be assigned and available by Week 3 for threshold configuration — without this, matching cannot go live.

Leave a Reply

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