Drugs and formularies
FDA Warning Letters
Rows
3,673
Columns
23
History
2021-01-04 (earliest letter_issue_date; single ingest snapshot dated 2026-05-16) to 2026-04-21 (latest letter_issue_date; posted_date extends to 2026-04-28)
Card
yesgrain, traps, filters
Typed tools
0
What it is
- 1A silver-layer mirror of the FDA's public Warning Letters dataset (the official FDA "datatables" export): one record per FDA warning letter issued to a company for a regulatory violation.
- 2Despite living in the drug catalog, it spans ALL FDA centers (tobacco, drugs, devices, food, veterinary, biologics), so it is a regulatory-enforcement signal — useful for flagging drug manufacturer / compounder / API-maker GMP and unapproved-drug actions that can disrupt supply, not a price or cost table itself.
Grain
| Key | Grain |
|---|---|
letter_id |
|
How to read it
- 1Surface drug-supply-disruption / enforcement risk for a manufacturer or compounder.
- 2Example: SELECT company_name, letter_issue_date, subject, issuing_office, closeout_letter_date FROM drug_silver.fact_fda_warning_letter WHERE (lower(issuing_office) LIKE '%cder%' OR lower(issuing_office) LIKE '%pharmaceutical quality%' OR lower(subject) LIKE '%pharmaceutical%' OR lower(subject) LIKE '%compounding%' OR lower(subject) LIKE '%api%') ORDER BY letter_issue_date DESC; — returns recent FDA drug-side warning letters (GMP/adulteration/unapproved-drug actions). closeout_letter_date IS NULL flags violations not yet formally resolved.
- 3Join to cost/manufacturer tables is name-based only (no shared code).
Traps
- 1NOT a cost/price table and NOT drug-only. It holds zero prices, NDCs, NPIs, or labeler codes. It spans ALL FDA centers — tobacco (868 letters) is actually the single biggest bucket, ahead of drugs. Drug-relevant rows are a large minority: ~773 by CDER/pharma-quality issuing_office, ~687 by drug-related subject. Always filter by subject/issuing_office (with LIKE, never equality) before treating it as a drug signal.
- 2letter_id looks like a content hash but IS the verified primary key (16-char hex, 2,571 unique = row count). Do not assume it's an unstable surrogate — the natural key (company+issue_date+subject) collapses to the exact same 2,571, so it is a deterministic 1:1 letter identifier.
- 3Single snapshot only (observed_period = asserted_at = vintage_tag date = 2026-05-16; cms_vintage_sequence, parse_revision, source_id, source_url, sha256_content_hash, s3_version_id are ALL single constants; is_current is trivially all-true). There is no history/time series here despite the bitemporal columns — periodicity is effectively static until the next pull. Do NOT read effective_period_start as a snapshot dimension: it just mirrors letter_issue_date 1:1.
- 4Three columns are null-as-meaning / dead: response_letter_date is 100% null (1 stray row), closeout_letter_date is 89% null where non-null = FDA formally resolved the violation (and null does NOT reliably mean 'still open' — it may just be un-closed-out publicly), and drug_source_version_id is 100% null. effective_period_end is always the 2099-12-31 open sentinel.
- 5issuing_office is unnormalized free text with 120+ values and heavy spelling drift for the same office (e.g. CDER appears as 'Center for Drug Evaluation and Research (CDER)', '... | CDER', 'Center for Drug Evaluation and Research', 'Drug'). Bucketing requires fuzzy/LIKE logic; an exact GROUP BY will badly fragment counts. company_name has the same risk for entity joins (free text, no identifier).
Columns (23)
| Column | Type | Meaning |
|---|---|---|
letter_id | string | PRIMARY KEY. 16-char lowercase-hex surrogate hash (verified: all 2,571 are 16 hex chars, all unique). Deterministically derived from letter identity (company+issue_date+subject all collapse to the same 2,571 distinct count). Stable join key for a single letter. |
letter_issue_date | date | Date FDA issued/sent the warning letter. Non-null 100%. Ranges 2021-01-04 to 2026-04-21. This is the primary event date. (effective_period_start mirrors it exactly.) |
posted_date | date | Date the letter was published to FDA's public website. Non-null 100%. Always >= letter_issue_date except 1 row (posting lags issuance by days–weeks). Ranges 2021-01-05 to 2026-04-28. |
company_name | string | Free-text name of the recipient firm (manufacturer, compounder, importer, vape shop, food processor, telehealth seller, etc.). Non-null, no blanks; 2,508 distinct over 2,571 rows (a few firms got multiple letters). NOT keyed to any NPI / labeler / DUNS code — join to cost entities requires fuzzy name matching. |
issuing_office | string | FDA office/center that issued the letter. VERY dirty free text: 120+ values with many near-duplicate spellings (e.g. 'Center for Drug Evaluation and Research (CDER)' vs '... | CDER'). Top buckets: Center for Tobacco Products (868), CDER drug offices (~600 across variants), Devices (158), Food/CFSAN, import divisions, Veterinary, Biologics. 3 rows null. Use LIKE-based bucketing, not equality, to find drug letters. |
subject | string | FDA's official violation-category string, slash-delimited (e.g. 'CGMP/Finished Pharmaceuticals/Adulterated', 'Unapproved New Drugs/Misbranded', 'Compounding Pharmacy/Adulterated Drug Products', 'Foreign Supplier Verification Program (FSVP)'). Non-null, no blanks. This is the 'reason' field — the most analytically useful column for filtering drug-relevant enforcement. |
response_letter_date | date | DEAD COLUMN in this snapshot: 100% null except 1 row (and that single row's issuing_office is mislabeled). Intended to hold the date FDA acknowledged the firm's response, but effectively unpopulated — do not rely on it. |
closeout_letter_date | date | Date FDA issued a close-out letter formally resolving the violation. 89.1% null (set on only 279 rows). Non-null => the warning was closed out / corrected; null => open OR simply never closed-out-publicly. Ranges 2021-05-12 to 2026-04-28. |
observed_period | date | Snapshot/ingest provenance date (bitemporal 'observed'). Constant 2026-05-16 for all rows — the single date this dataset was pulled. Not a per-letter date. |
asserted_at | date | Bitemporal 'asserted' timestamp (when the fact was written to silver). Constant 2026-05-16 — equals observed_period; single ingest. |
effective_period_start | date | Bitemporal validity start. Verified to EQUAL letter_issue_date on 100% of rows — carries no new information beyond letter_issue_date. The profiler labels this the time column. |
effective_period_end | date | Bitemporal validity end. Always the sentinel 2099-12-31 (open / not superseded) on all 2,571 rows — every record is the current version. |
cms_vintage_sequence | int | Vintage sequence counter for the source pull. Constant = 1 (only one vintage ingested). 'cms_' prefix is a shared-schema artifact; this is FDA data, not CMS. |
parse_revision | int | Parser revision number. Constant = 1 — only one parse generation present. |
parser_artifact_hash | string | SHA-256 of the parser code/artifact that produced these rows (lineage). Single constant value across all rows (one parser version). |
source_url | string | Origin URL: the FDA warning-letters 'datatables-data' export page (https://www.fda.gov/.../warning-letters/datatables-data). Single constant value. |
sha256_content_hash | string | SHA-256 of the raw downloaded source file. Single constant value (one source file underlies all rows). |
source_id | string | Logical source identifier = 'fda_warning_letters' on every row. Single constant. |
is_current | boolean | Snapshot currency flag. TRUE on 100% of rows — there is only one snapshot, so no superseded/historical rows exist yet. Filtering on is_current=true is a no-op today but is the forward-compatible pattern. |
bronze_object_key | string | S3 key of the bronze source object: drug/bronze/fda_warning_letters/2026-05-16/<hash>-fda_warning_letters_2026-05-16.xlsx (an Excel export). Single constant — confirms one source file. |
s3_version_id | string | S3 object version id of that bronze file (lineage). Single constant value. |
vintage_tag | string | Human-readable vintage label = 'fda_warning_letters_2026-05-16'. Single constant — identifies the one snapshot. |
drug_source_version_id | string | DEAD COLUMN: 100% null. Intended FK to a drug source-version registry but never populated for this source. |
Query it
describe_data_source(source_fqn="drug_silver.fact_fda_warning_letter") # the card, live query_substrate(sql="SELECT * FROM drug_silver.fact_fda_warning_letter WHERE letter_id = '<value>' LIMIT 100")
| Item | Value |
|---|---|
| Typed tools that read it | none; raw SQL |
| Identity key | letter_id |
| Join | how_to_join(source_fqn="drug_silver.fact_fda_warning_letter") |
| Raw door | Athena (read-only via query_substrate): drug_silver.fact_fda_warning_letter |
This page as markdown: /docs-md/data/drug_silver_fact_fda_warning_letter.md · every page in one file: /llms-full.txt