Enterprise Context Layer: Overlay Pattern

An overlay pattern that introduces enterprise semantics without modifying two decades of pipelines. Worked through single-family mortgage delivery.

This is my perspective on how an enterprise context layer can be built in large organizations that have two decades of data foundations already in place. I have written it for the practitioner who has to propose this pattern inside their own organization: the architect who then sits across from the tech leader whose warehouse is being ringfenced, the platform engineer whose pipelines are being asked to stay untouched, and the business owner whose team owns the definitions.

The technical argument is the easy half; the rest of what follows is about how to get the pattern past the meeting where it might otherwise be killed, respectfully and with the grain of the room. I have picked an example from the secondary mortgage business (specifically the single-family loan lifecycle followed by GSEs such as Fannie Mae and Freddie Mac) because it is a domain I have been close to across my career, and one where the public data standards (MISMO, ULDD, UAD, the GSE Selling Guide) let me anchor the walkthrough in published detail rather than in anything proprietary.

Note: The standards, systems and regulatory dates referenced here are public. Every loan-level value in the worked example is invented for the walkthrough. Nothing here describes the internal architecture of any employer, past, present, or prospective, and nothing draws on proprietary or non-public information.

1The problem, stated honestly

Why the obvious answer is unaffordable, and what remains once you accept that.

Every large regulated enterprise has arrived at roughly the same analytics architecture, and it took about two decades to get there. Source-aligned ingestion into a data lake on a near real time cadence. An integrated data model beneath it that conforms and integrates across sources. Then consumption in two shapes: wide snapshots for analytics, dimensional marts for reporting. Thousands of pipelines run against that stack every day. Hundreds of downstream consumers depend on its output. The people who built the earliest parts of it have retired.

Into that estate arrives a new requirement. Agents need grounding. Regulators want to know why a decision was made. Executives want one definition of a term rather than four. The vendor answer is a semantic layer, and the vendor diagram always shows it sitting in the middle of the architecture, which means re-plumbing the middle of the architecture.

The constraint that kills the obvious answer: There is no cost-effective path to introducing a semantic layer that requires material change to the existing pipelines, the integrated model, or the marts. Not because the engineering is hard, but because the change management is impossible. You cannot ask four hundred pipeline owners to accept a new dependency, and you cannot remodel a twenty-year-old integrated model without a multi-year program that will be cancelled in year two when leadership changes.

So the design problem is not what is the ideal semantic architecture. It is what is the most semantics you can add while touching nothing.

What the estate already gives you, and what it does not

The instinct many partners will have is that conformed ETL already solved this. It did not, and being precise about why is the difference between a credible proposal and a rejected one.

The estate providesWhich meansBut it does not provide
Conformed structure Consistent grain, consistent types, consistent keys within the warehouse Conformed meaning. A dimensional model can be immaculate and still carry four definitions of delinquency, because nothing in the model forces a business term to resolve to one thing.
Local keys Joins work inside the warehouse Stable global identity for the same real world thing across systems, and no place to record the aliases it carries elsewhere.
Foreign keys Relationships you can join if you already know they exist Relationships as first class objects you can traverse without knowing the path in advance.
Facts and dimensions What was true, as of a load Decision traces. What was asserted, by which system, under which rule version, at which moment. Dimensional ETL drops these because they are not facts in the dimensional sense.

Structure and semantics are separate problems. Solving the first does not solve the second, and two decades of excellent work on the first is exactly why the second is now the binding constraint.

2Design principles

Five rules. Every decision in the architecture falls out of them.

The invariant

That last line is what makes the proposal survivable inside a large organization. It is what lets an operational executive commit to the pattern without commissioning a separate risk assessment first.

Principle 1 · Bind to the integrated model, not to the lake or the marts

Principle 2 · The ontology binds to the estate; the estate does not bend to the ontology

Principle 3 · Separate design time from run time

Principle 4 · The graph holds relationships; the estate holds values

Principle 5 · The binding catalogue is the deliverable, not the graph

Why this design becomes economically rational as the estate grows.

Suppose 10 source systems each hold a value for the term "delinquency," and all 10 need to agree on what it means.

Option A: reconcile every pair. Each pair of systems builds and maintains its own bilateral agreement. Ten systems have 45 possible pairs (10 × 9 ÷ 2). Twenty systems have 190. Each new system does not add one more reconciliation; it adds one for every system already in the estate.

Option B: bind each system to one central definition. Every system maps its value to the same shared meaning. Ten systems means 10 sets of bindings. Twenty means 20. Each new system adds exactly one set, whatever the size of the estate.

Bindings scale with the number of systems. Pairwise reconciliation scales with the number of pairs between them. Central context costs more to set up than any single bilateral agreement. But once more than a handful of systems need to agree on the same term, central context is already cheaper. And it wins more decisively with every source added after that.

3System context

Thirteen numbered boxes in four bands. Boxes 1 to 4 already exist and are not modified. Boxes 5 to 13 are the entire proposal.

Enterprise Context Layer system diagram: four bands (design time, existing estate, run time overlay, consumers) with thirteen numbered boxes and their read-only relationships

Click the diagram to view at full size. Read order: 5 to 8 is the build. 1 to 4 is what already exists. 9 through 12 are the run-time overlay. Box 3 is the only place the two worlds touch, and that contact is read-only in one direction and a query pushdown in the other.

4The boxes

What each one is, what it does, what it deliberately does not do, and what breaks if it is wrong.

1 Source systems Existing

2 Source-aligned data lake Existing

3 Integrated data model Binding anchor

4 Analytics and reporting consumption Existing

5 Ontology authoring Design time

6 Physical binding catalogue Design time

7 Version control and release Design time

8 Model deployment Design time to run time

9 Identity spine builder Run time

10 Decision trace loader Run time

11 Runtime context graph Run time

Choosing the store

If the workload isThenBecause
Bounded depth, known path, aggregationRelational or lakehouseIt is a join. Cheaper, mature, and you already have the staff. Worth naming early in the design conversation rather than defending after the fact.
Variable depth, unknown hop count, relationship discoveryProperty graphRecursive common table expressions degrade and you cannot index your way out.
Formal inference, classification against axioms, standards interchangeRDF triplestoreYou need a reasoner and global identifiers, which a property graph does not give you.

12 Federated attribute resolution Run time

13 Consumers Run time

5Steel thread: one loan, end to end

Every value below is invented for this walkthrough. The mechanics are real; the loan is not.

The question this thread answers is the narrow, high stakes one at delivery. Is the loan being delivered the same loan that underwriting approved? The selling guide is explicit that the final underwriting submission must match the terms of the closed loan and must carry an eligible recommendation, and that representation and warranty relief is tied to those findings. So the question is not academic.

The loan

AttributeValueWhere it lives
Enterprise loan number9001234567Assigned at delivery. Chosen as the canonical key.
Underwriting casefile1451220987Alias. Deterministic.
Lender loan numberLN-88213Alias. Seller's own key.
MERS registration number100012300000088213Alias. Survives servicing transfer.
Pool numberAL7742Alias. Present only for pool deliveries.
Property4412 Old Mill Road, Ashburn VA 20147 · parcel 058-27-1140Probabilistic match. No universal property identifier exists.
Note amount480,000Integrated model. Reached at query time.
Appraised value600,000Integrated model.
Loan to value80.0Integrated model.
Debt to income41.2 at underwriting, 43.8 at closingThe discrepancy this thread finds.

The story behind those two numbers: borrower income was restated between the final underwriting submission and closing. The note reflects the corrected figure. The findings on file reflect the earlier one. Today this surfaces either in the delivery application's own comparison, if that field happens to be in scope for it, or months later in post-purchase quality control sampling, when the remedy is a repurchase conversation rather than a correction.

Step 1 · Box 5: the ontology fragment

Small on purpose. Two properties and three relationships carry the entire thread.

@prefix sf:  <https://example.org/ont/sf#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix fibo: <https://spec.edmcouncil.org/fibo/ontology/LOAN/LoansGeneral/Loans/> .

sf:Loan a owl:Class ;
  rdfs:subClassOf fibo:Loan ;
  rdfs:label    "Single-family loan"@en .

sf:hasCanonicalId a owl:DatatypeProperty ;
  rdfs:domain    sf:Loan ;
  rdfs:range     xsd:string ;
  rdfs:label     "canonical loan identifier"@en .

sf:LifecycleState a owl:Class .
sf:Underwriting  a sf:LifecycleState ; sf:authoritativeSystem "Desktop Underwriter" .
sf:Closing    a sf:LifecycleState ; sf:authoritativeSystem "UCD collection" .
sf:Delivery    a sf:LifecycleState ; sf:authoritativeSystem "Loan Delivery" .

sf:debtToIncomeRatio a owl:DatatypeProperty ;
  rdfs:domain  sf:Loan ;
  rdfs:range  xsd:decimal ;
  rdfs:label  "debt to income ratio"@en ;
  rdfs:comment "Total monthly obligations over qualifying monthly income, in percentage points." ;

  # The two lines that carry the whole political argument:
  sf:authoritativeAt sf:Closing ;
  sf:assertedAt    sf:Underwriting, sf:Closing, sf:Delivery .

sf:securedBy a owl:ObjectProperty ; rdfs:domain sf:Loan ; rdfs:range sf:Property .
sf:hasTrace a owl:ObjectProperty ; rdfs:domain sf:Loan ; rdfs:range sf:DecisionTrace .
Note what authoritativeAt and assertedAt do: One lifecycle state is authoritative for a term; several states may assert it. Each state carries the system that owns it: underwriting sits with Desktop Underwriter, closing with the UCD collection, delivery with Loan Delivery. For debt-to-income, closing is the authoritative state, which means the UCD collection value is the trusted one. Underwriting and delivery both assert the term too, and their assertions are recorded but not the source of truth. That two-step, from term to authoritative state to authoritative system, is the whole answer to our system is the source of truth, expressed as machine-readable metadata rather than as a position in a meeting. Authority becomes explicit and queryable instead of tribal.
Step 2 · Box 6: the physical binding

The catalogue entry carries far more than a location. The last four fields are the ones that stop this from becoming a data dictionary nobody trusts.

- term: sf:debtToIncomeRatio
 binds_to:
  layer:      integrated_data_model
  object:      IDM.LOAN_CORE
  column:      DTI_RATIO_PCT
 grain:       one row per loan, current state
 precision:     decimal(5,2), percentage points, not a fraction
 authoritative_at:  Closing
 null_semantics:   "NULL means not yet closed. NULL is not zero."
 upstream_lineage:  UCD collection -> STG_UCD_CLOSING -> IDM.LOAN_CORE (job UCD_LOAD v14)
 domain_owner:    Single-Family Origination Data
 signed_off:     2026-07-14
 introduced_in:   release 2026.3

Where the runtime is RDF, the same declaration is expressed as a standards-based mapping:

<#LoanCoreMap> a rr:TriplesMap ;
 rr:logicalTable [ rr:tableName "IDM.LOAN_CORE" ] ;
 rr:subjectMap  [ rr:template "https://example.org/loan/{ENTERPRISE_LOAN_NBR}" ;
          rr:class   sf:Loan ] ;
 rr:predicateObjectMap [
  rr:predicate sf:debtToIncomeRatio ;
  rr:objectMap [ rr:column "DTI_RATIO_PCT" ; rr:datatype xsd:decimal ] ] .

This is a declaration, not a transformation. It is authored once and then evaluated continuously, either at materialization time or at query time. It is closer to a view definition than to an ETL job, and that distinction is why it does not add load to the estate.

Step 3 · Boxes 7 and 8: release and deploy
Step 4 · Box 9: build the identity spine

Read-only against the integrated model. Note what is absent: no note amount, no rate, no debt to income. Identity and edges only.

// One canonical loan, every source identifier kept as an alias.
MERGE (l:Loan {canonicalId: $enterpriseLoanNbr})
 ON CREATE SET l.createdAt = datetime(),
        l.uri    = 'https://example.org/loan/' + $enterpriseLoanNbr

WITH l
UNWIND $aliases AS a
 MERGE (x:Alias {scheme: a.scheme, value: a.value})
 MERGE (l)-[r:IDENTIFIED_BY]->(x)
  SET r.confidence = a.confidence, r.basis = a.basis, r.observedIn = a.system;

// $aliases for this loan:
//  {scheme:'DU_CASEFILE', value:'1451220987',     confidence:1.00, basis:'deterministic'}
//  {scheme:'LENDER_LOAN', value:'LN-88213',      confidence:1.00, basis:'deterministic'}
//  {scheme:'MERS_MIN',  value:'100012300000088213', confidence:1.00, basis:'deterministic'}
//  {scheme:'POOL',    value:'AL7742',       confidence:1.00, basis:'deterministic'}

// Property resolution is probabilistic, and the confidence travels with the edge.
MERGE (p:Property {canonicalId: $propertyKey})
MERGE (l)-[s:SECURED_BY]->(p)
 SET s.confidence = 0.94,
   s.basis   = 'address normalised + parcel match; fuzzy on unit designator';
Step 5 · Box 10: load the decision traces

Read from the lake, because the integrated model kept the outcome and discarded the rationale. Append-only, immutable, each carrying the rule version in force.

MATCH (l:Loan {canonicalId: '9001234567'})

MERGE (uw:DecisionTrace {eventId: 'DU-1451220987-FINAL'})
 SET uw.type    = 'UNDERWRITING_FINAL',
   uw.system   = 'Desktop Underwriter',
   uw.occurredAt = datetime('2026-03-12T14:22:07Z'),
   uw.ruleVersion = 'DU 11.1',
   uw.outcome   = 'Approve/Eligible',
   uw.keyedOn   = 'DU_CASEFILE:1451220987',
   uw.asserted  = {debtToIncomeRatio: 41.2, loanToValueRatio: 80.0, noteAmount: 480000}
MERGE (l)-[:HAS_TRACE]->(uw);

MERGE (cl:DecisionTrace {eventId: 'UCD-LN88213-CLOSING'})
 SET cl.type    = 'CLOSING',
   cl.system   = 'UCD collection',
   cl.occurredAt = datetime('2026-03-20T00:00:00Z'),
   cl.keyedOn   = 'LENDER_LOAN:LN-88213',
   cl.asserted  = {debtToIncomeRatio: 43.8, noteAmount: 480000}
MERGE (l)-[:HAS_TRACE]->(cl);

MERGE (dl:DecisionTrace {eventId: 'ULDD-9001234567-SUB1'})
 SET dl.type    = 'DELIVERY_SUBMISSION',
   dl.system   = 'Loan Delivery',
   dl.occurredAt = datetime('2026-04-02T09:41:00Z'),
   dl.ruleVersion = 'ULDD Phase 5 (5.2.0)',
   dl.outcome   = 'No fatal edits',
   dl.keyedOn   = 'ENTERPRISE_LOAN:9001234567',
   dl.asserted  = {debtToIncomeRatio: 43.8, loanToValueRatio: 80.0, noteAmount: 480000}
MERGE (l)-[:HAS_TRACE]->(dl);

Values appear on a trace because a trace is a record of what was asserted at a moment. Reaching into the estate for the current value would defeat the purpose, since the current value is precisely what may have moved. This is the deliberate exception to the rule that the graph holds no payload.

Step 6 · Box 13: ask the question
MATCH (l:Loan)-[:HAS_TRACE]->(uw:DecisionTrace {type: 'UNDERWRITING_FINAL'})
MATCH (l)-[:HAS_TRACE]->(dl:DecisionTrace {type: 'DELIVERY_SUBMISSION'})
WHERE dl.occurredAt > uw.occurredAt
 AND abs(dl.asserted.debtToIncomeRatio - uw.asserted.debtToIncomeRatio) > $tolerance
RETURN l.canonicalId          AS loan,
    uw.asserted.debtToIncomeRatio  AS dtiAtUnderwriting,
    dl.asserted.debtToIncomeRatio  AS dtiAtDelivery,
    uw.ruleVersion          AS underwritingVersion,
    uw.outcome            AS underwritingOutcome,
    duration.between(uw.occurredAt, dl.occurredAt).days AS daysElapsed
ORDER BY abs(dl.asserted.debtToIncomeRatio - uw.asserted.debtToIncomeRatio) DESC;
loandtiAtUnderwritingdtiAtDeliveryunderwritingVersionunderwritingOutcomedaysElapsed
900123456741.243.8DU 11.1Approve/Eligible21
Step 7 · Box 12: reach for a value the graph does not hold

The finding raises a follow-up: what does the enterprise currently hold as authoritative for this loan? The graph has no idea, and should not. It resolves the identity and hands off to box 12, which uses the binding from box 6 to rewrite the query and execute it against the estate.

# Asked against the model
SELECT ?dti WHERE {
 ?loan a sf:Loan ;
    sf:hasCanonicalId   "9001234567" ;
    sf:debtToIncomeRatio ?dti .
}

# Executed on the estate
SELECT DTI_RATIO_PCT
FROM  IDM.LOAN_CORE
WHERE ENTERPRISE_LOAN_NBR = '9001234567';

What just happened, and what did not

The honest limit, worth naming up front in any proposal of this pattern: Whether a 2.6 point move in debt to income is a defect is a policy question, not a data question. Income can legitimately be restated between underwriting and closing, and the resubmission rules exist precisely because that happens. The context layer surfaces that three systems assert different values and shows exactly what each asserted and when. It does not adjudicate, and a design that claims to adjudicate will be correctly distrusted by the people who own the policy.

6Objections, and what to concede

Every practitioner proposing this pattern will meet an executive who has sat through three vendor pitches and will test the limits. Concede first and you take the weapon away.

Why not just extend the integrated model?

Conformed dimensions already solved this

How is this different from the catalogue we already bought?

Who owns the ontology when two business units disagree on a definition?

What does it cost?

Will the graph drift from the warehouse?

Is this not just another metadata project that dies in year two?

7Sequencing, and what this does not do

The failure mode is scope, not technology.

Sequence

What this deliberately does not do

8The people equation

Centralize the mechanism. Federate the meaning.

The pattern above works when the roles behind it work. A design that funnels every domain through a central data team fails on the same schedule as a design that leaves every domain to invent its own semantics. The organizing rule is short: centralize the mechanism, federate the meaning.

The failure mode at both extremes is easy to name. A central council that approves every definition dies of throughput. A pure federation dies of divergence. This pattern deliberately lives between them.

A follow-up piece in this series will work through the operating model in detail: who signs off on what, how the roles line up against a typical enterprise data organization, what a RACI looks like across a full lifecycle, and where the pattern breaks when any of those roles goes missing.

Who owns what, at a glance:

 

What this pattern earns:

In closing: Enterprise AI does not succeed on the strength of its models. It succeeds on the strength of the context it acts against. The estate already holds almost everything an autonomous agent, an examiner, or a definition-hungry mart needs. What it lacks is a shared, executable, versioned agreement about what that data means, held somewhere the machines can reach and the humans can govern. Without it, Enterprise AI keeps producing plausible answers to questions no one can defend afterwards. With it, the same data foundation that has run the business for two decades runs the next generation of it too. That agreement is cheap to build and expensive to keep, and the keeping is the job.
 

Acronyms and abbreviations

TermMeaning
IDMIntegrated data model. The conformed, business-facing warehouse layer that sits between the source-aligned lake and the analytics and reporting marts. In this piece, the binding anchor.
MISMOMortgage Industry Standards Maintenance Organization. The U.S. mortgage industry's data-standards body.
FIBOFinancial Industry Business Ontology. Published by the EDM Council in RDF and OWL. Used here as the upper model for the loan domain.
ULDDUniform Loan Delivery Dataset. Fannie Mae's data standard for loan delivery, built on MISMO with GSE extensions.
UADUniform Appraisal Dataset. Fannie Mae's data standard for appraisals.
UCDUniform Closing Dataset. Fannie Mae's data standard for closing.
UCDPUniform Collateral Data Portal. Where lenders submit appraisal reports.
CUCollateral Underwriter. Fannie Mae's appraisal analytics engine, which scores UAD-formatted appraisals.
DU / DODesktop Underwriter (lender-facing) and Desktop Originator (broker-facing). Fannie Mae's automated underwriting engine.
MERSMortgage Electronic Registration Systems. Registry that survives servicing transfer.
DRSDefault Reporting System. Fannie Mae's servicer-facing system for reporting on delinquent and defaulted loans.
GSEGovernment-Sponsored Enterprise. In this piece, Fannie Mae and Freddie Mac.
DTIDebt-to-income ratio.
LTVLoan-to-value ratio.
QCQuality control. Post-purchase sampling and review of delivered loans.
OWLWeb Ontology Language. W3C standard for expressing ontologies.
RDFResource Description Framework. W3C standard for representing information as subject-predicate-object triples.
SPARQLSPARQL Protocol and RDF Query Language. W3C query language for RDF.
LPGLabeled property graph. The data model used by Neo4j and similar property graph databases.
OBDAOntology-based data access. Query pattern where a SPARQL query is rewritten at runtime to a native store query, usually SQL.
R2RMLRDB-to-RDF Mapping Language. W3C standard for expressing relational-to-RDF mappings.
RMLRDF Mapping Language. Generalization of R2RML to non-relational sources.
n10sneosemantics. Neo4j plugin that loads RDF and interoperates with RDF tooling.
TTLTurtle. RDF serialization format.
CDCChange data capture.
ETLExtract, transform, load.
CIContinuous integration.
RACIResponsible, Accountable, Consulted, Informed. Role-assignment matrix used in operating models.
PRPull request.

References

Standards, tools, and domain publications cited or used to build this piece.

Ontology and semantic web standards

Binding, mapping, and query rewriting

Mortgage industry data standards

Operational systems referenced