---
cuppy_hub: aws
cuppy_path: examples/healthcare-master-data/08-gaps-and-custom-code-register.md
cuppy_section: docs
cuppy_doc: W2JS-PC7V
cuppy_doc_uuid: 458bd284-b90e-485b-a382-3056d9307f79
cuppy_permalink: https://cuppy.io/aws/d/W2JS-PC7V
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/aws/docs/examples/healthcare-master-data/08-gaps-and-custom-code-register
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 4f2d9eef3606ab0d75248e7c574b860d1e80433cbca5f5a3b7f82e8c5e241c71
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Gaps and custom-code register

A licensed MDM product is mostly not a matching engine. It is a matching engine wrapped in years of
workflow, user interface, governance metadata and operational machinery. This register names what
you take on when you decline the licence.

Two kinds of entry appear here. An **evidenced gap** rests on a sentence from an AWS page stating a
limit. A **documented silence** means the cited pages say nothing either way; it is a gap because an
unstated capability cannot be designed on, not because AWS called it absent. Every row is marked.

## Severity and effort keys

| Severity | Meaning |
| --- | --- |
| S1 | Required for first production use; nothing ships without it |
| S2 | Required within the first release cycle; a manual workaround can bridge weeks, not months |
| S3 | Degrades quality or operability; schedulable |

| Effort | Meaning |
| --- | --- |
| E1 | Days — configuration, a rules table, a Lambda function |
| E2 | Weeks — a service, a schema, tests, a pipeline stage |
| E3 | Months — an application with its own authorisation and audit surface |

## The register

| # | Gap | Sev | Effort | Basis |
| --- | --- | --- | --- | --- |
| G1 | Per-attribute survivorship rules | S1 | E2 | Silence |
| G2 | A durable, versioned golden-record store | S1 | E2 | Evidenced |
| G3 | Stable master identifier and crosswalk | S1 | E2 | Silence |
| G4 | Steward review, merge and unmerge UI | S1 | E3 | Silence |
| G5 | Steward decisions surviving reprocessing | S1 | E2 | Evidenced |
| G6 | Reconciling two matching engines | S2 | E2 | Evidenced |
| G7 | Multi-dimensional dated hierarchies | S2 | E2 | Evidenced |
| G8 | Publishing golden records to consumers | S2 | E2 | Partly evidenced |
| G9 | Attribute-level lineage and provenance | S2 | E2 | Silence |
| G10 | Data quality remediation workflow | S2 | E2 | Evidenced |
| G11 | Reference data and code-set management | S2 | E2 | Silence |
| G12 | Match-quality measurement harness | S2 | E2 | Silence |
| G13 | HealthLake matching is Preview — PHI eligibility | S1 | E1 | Evidenced |
| G14 | HealthLake is absent from AWS Backup | S2 | E2 | Evidenced |
| G15 | Audit Manager closed to new accounts | S2 | E1 | Evidenced |
| G16 | One concurrent matching job per Region | S2 | E1 | Evidenced |
| G17 | No automatic incremental processing for ML | S3 | E1 | Evidenced |
| G24 | Analytics views are pseudonymised, not de-identified | S1 | E2 | Evidenced |
| G18 | Rule-based matching is exact, not fuzzy | S2 | E2 | Evidenced |
| G19 | Glue DQ cannot flag failing rows from the catalog | S3 | E1 | Evidenced |
| G20 | De-identification is not a managed control | S2 | E2 | Evidenced |
| G21 | Macie covers S3 only | S3 | E2 | Evidenced |
| G22 | Break-glass access path | S1 | E2 | Silence |
| G23 | Entity Resolution has no FHIR awareness | S2 | E2 | Silence |

## The entries that decide the design

**G1 — survivorship.** No cited page mentions survivorship, trust scores, source precedence or
golden records for either matching service. Build a rules table keyed by entity type and attribute,
with a strategy per attribute (most recent, most trusted source, longest non-null, clinically
validated), and a deterministic evaluator in Lambda or Glue. Make it data, not code, so a steward
can change a precedence without a deployment, and keep it pure: the same inputs must always produce
the same golden record.

**G2 — the golden-record store.** Entity Resolution writes "the data output in your Amazon Simple
Storage Service (Amazon S3) bucket" with match groups — a file, not a system of record. Aurora
PostgreSQL holds the master entity, its attribute-level provenance and its version history; the
match output is an input to it.

**G3 — the master identifier.** The sharpest gap in the set. The glossary defines a match ID as "the
ID generated by AWS Entity Resolution and applied to each matched record set ... part of the
matching workflow metadata that will be included in output". Nothing cited here states that the
match ID for one real-world entity is identical across separate bulk runs; the only stability
sentence, "a record's match ID is fixed upon its first match", is scoped to transitive matching
inside a run. What *is* documented is narrower than total instability: `GenerateMatchId` "retrieves
their Match IDs and associated rules" for existing records, and bulk processing applies "updates to
existing matches", so match IDs do persist for records already held in a live workflow's results.
What nothing warrants is stability across workflow recreation, a rule-set change or a switch between
rule-based and ML — which is exactly the case a rebuild hits.

So mint your own enterprise identifier, persist it, and resolve match IDs to it every run;
downstream consumers must never see a match ID. Two cheap measures turn this from an unrecoverable
component into a recoverable one, and they are worth more than backing it up harder. First, write
every crosswalk mutation as an append-only journal record into the Object Lock raw zone, so the
mapping is derivable from immutable storage like every other value in the design. Second, derive
`master_id` deterministically where the inputs allow — a keyed hash of the earliest stable scoped
identifier tuple — so a rebuild converges on the same identifiers for the unambiguous majority and
only the steward-adjudicated minority needs the journal.

**G4 — the steward console.** This is the largest single piece of work and the honest answer to why
licensed MDM products still sell. A licensed product ships a data steward workbench: a queue of
candidate matches, side-by-side comparison, attribute-level accept and override, merge and unmerge,
an audit trail per decision, and role-scoped access. None of that exists in the services cited
here. Budget it as E3 and build it as a PHI-handling application in its own right — IAM Identity
Center or Cognito for authentication, Lake Formation or application-level row filtering, CloudTrail
for API audit, and a full access review.

**G5 — decisions must survive reprocessing.** Bulk processing "re-processes all data for any new
matches and updates to existing matches", and a steward's verdict is not an input to that job — so
without a persisted override store a human decision is silently reversed on the next run. Hold
overrides in Aurora and apply them after matching, as a deterministic post-pass.

**G13 — the Preview question.** The eligible services page extends eligibility with this caveat:
"Unless specifically excluded, generally available features of each of the HIPAA eligible services
listed are also considered HIPAA eligible." HealthLake resource matching is labelled "available as a
preview capability and is subject to change", and the Data Transformation Agent is also Preview. A
Preview feature is not generally available, so the cited pages do not establish that PHI may be
processed by those features under the BAA. That is an inference from two quotes, not an AWS
statement, and a question for an AWS account team rather than one a documentation page settles.
Until it is resolved: architect production on AWS Entity Resolution, which is generally available
and listed without exclusion, and pilot HealthLake matching on synthetic or de-identified data.

**G14 — HealthLake and AWS Backup.** The AWS Backup feature availability page lists its supported
resources and states "Support for a feature or service should not be assumed unless explicitly
mentioned". AWS HealthLake appears nowhere on it. Recovery for the FHIR store must therefore be
assembled from the service's own FHIR export plus the immutable source log in S3. See document 06.

**G15 — Audit Manager.** Its documentation now states "AWS Audit Manager is no longer open to new
customers", after a cutoff dated 30 April 2026 that has passed. The HIPAA Security Rule: Feb 2003
framework still exists for existing customers — 24 automated and 61 manual controls across 5 control
sets — but a new landing zone cannot adopt it. AWS directs customers to Config conformance packs;
both HIPAA frameworks map to `Operational-Best-Practices-for-HIPAA-Security`. Configuration, not
code, but decide before the landing zone is built.

**G16 and G17 — throughput and cost shape.** "Concurrent matching jobs — Each supported Region: 1 —
Adjustable: No", so entity workflows must be serialised. Separately, automatic incremental
processing is documented "for rule-based matching scenarios" only, the glossary confirming it "is
available for rule-based matching only". The glossary does define a `RecordConfidenceLevel` "for ML
incremental matching", so an incremental ML path appears to exist, but its invocation is not
characterised in the cited pages. `07-cost-model.md` models ML as full reprocessing and marks that
a conservative assumption.

**G18 — exactness.** "Rule-based matching is process designed to find exact matches ... All match
keys provided within rule criteria must match exactly." Typos, nicknames and transposed birth dates
are not caught by rules, and the ML model that does catch them "uses all input fields associated
with name, email address, phone number, address, and date of birth data types" — no clinical
identifier among them. If your match quality target depends on fuzzy identifier matching, a
custom blocking-and-scoring pass in Glue is the fallback, and it is a real E2 of statistical work.

**G19 — Glue Data Quality's two entry points differ.** From the comparison table: rule
recommendations are supported from the Data Catalog and not from ETL jobs, while identifying the
records that failed a check is supported in ETL jobs and not from the Data Catalog. Run quality
checks inside the ETL job if you want a quarantine of failing rows. Also noted: "Data quality rules
can't evaluate nested or list-type data sources", which matters for FHIR-shaped data and means
flattening first. Limits cited here: 2,000 rules per ruleset, 65 KB per ruleset, 100,000 statistics
per account retained at most two years.

**G20 — de-identification.** Comprehend Medical's `DetectPHI` is the nearest managed primitive, and
its own page sets the boundary: "Amazon Comprehend Medical detects entities associated with these
identifiers but these entities don't map 1:1 to the list specified by the Safe Harbor method", with
a recommendation to "use additional human review or other methods to confirm the accuracy of
detected PHI". It is an aid to de-identifying free text, not a de-identification control, and a
Safe Harbor or expert-determination process remains a customer obligation. The Safe Harbor
identifier list is not enumerated in this document set; confirm it against HHS directly.

**G21 — Macie's scope.** Macie's managed data identifiers "detect sensitive data in Amazon Simple
Storage Service (Amazon S3) objects". Seven PHI-category sensitive-data types are listed, each
marked as requiring a nearby keyword. Macie is a control over your S3 landing and curated zones.
It is not a scanner for Aurora, DynamoDB, Redshift or HealthLake, and should not be presented
as one.

**G22 — break-glass.** No service cited here provides an emergency elevated-access workflow. Build
it: a separate role assumable only through a ticketed, time-boxed approval, every assumption raising
an EventBridge event and a Security Hub finding, with CloudTrail as the record and a mandatory
post-incident review. Treat the steward console's own emergency override the same way.

**G7 — hierarchies.** FHIR supplies representations: `Organization.partOf` gives a parent chain,
`OrganizationAffiliation` expresses other ties, and `PractitionerRole` links a practitioner to an
organisation. But `partOf` is cardinality 0..1 — one parent, no effective dating — and HealthLake
matching "does not link resources of different types". Nothing managed maintains them, so
multi-dimensional, effective-dated hierarchy management is yours.

**G24 — pseudonymisation is not de-identification.** A column-filtered analytics view that retains
`master_id` retains a code that re-identifies every row the moment it is joined to the crosswalk.
That is pseudonymised PHI — inside the BAA, inside the Data OU's controls — not de-identified data,
and not something to hand to a lower environment. A genuinely de-identified extract is a separate
build: remove the linking code or replace it with a per-extract value whose key is not disclosed,
then suppress, generalise and date-shift. Document 04 carries the wording to use.

**G23 — the FHIR seam.** Entity Resolution reads Glue tables; it has no FHIR resource model. Mapping
FHIR `Patient`, `Practitioner`, `Organization` and `Location` down to flat matchable columns and back
is custom transformation on both sides of the matcher.

**G8 — publishing, and what is already managed.** This entry is partly evidenced because part of it
is solved. HealthLake documents FHIR Subscriptions, priced per the pricing page as an Advanced-tier
capability with an EventBridge destination and a REST-Hook destination, and HealthLake names
EventBridge among its related services for routing data store events. So change notification out of
the FHIR layer is a managed capability, subject to that tier caveat. What remains custom is
publishing the *golden record* and the crosswalk out of Aurora: an outbox pattern, EventBridge for
fan-out, SNS or SQS per consumer, and a contract and schema version per subscriber. Nothing in the
cited pages supplies that.

## Build order

G2 and G3 first, because every later piece writes into them. Then G1 and G5 — survivorship plus
override replay makes the pipeline deterministic and re-runnable. Then G8 publish, so consumers can
be onboarded while G4 is still being built; a steward can work from a queue in a notebook for a
short while, and cannot work without one for long. G13 is a conversation to open on day one, not a
task. G15 and G16 are configuration decisions to get right before the landing zone is built, because
both are cheap now and expensive to retrofit.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 131 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/aws/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
