Gaps and custom-code register
Every capability a licensed MDM product supplies that AWS services do not, with severity, the custom approach, an effort class, and the evidence or documented silence behind each entry.
markdownexamplev1W2JS-PC7Vstage: designtrust: mixedservice: entity-resolutionservice: healthlakeservice: glueservice: auroraservice: step-functionsservice: configservice: backupinterface: architectureMDM capability gaps on AWSsurvivorship custom codestewardship user interface gapmaster identifier crosswalkHealthLake preview eligibility questionAudit Manager maintenance modeAWS Backup HealthLake absenceeffort classes and build order
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.