HMIS data quality toolkit

Loads an HMIS CSV export into a reporting database, runs 14 data quality checks, tracks agency follow-up and tests every backup by restoring it.

Status: demonstration, built October 2026. Every person, project and record is synthetic, generated with known problems planted at fixed rates. No client data is used. The files follow a subset of the HUD HMIS CSV export columns (Project, Client, Enrollment, Exit), so the same checks run against a real export.

Open the work

FileWhat it shows
Data quality report (PDF)Summary, findings by check, error rate by project, rules, example records and the database administration checks
flagged_records.csvOne row per flagged record, ready to split by agency
dq_summary.csvFlagged count, records checked and rate for each check and project
READMEHow to run it, how it is built and what each check finds
Source code and synthetic export (ZIP)Python 3 standard library, SQLite, SQL rules in one file

What the run found

Reporting period October 1, 2025 to September 30, 2026: 913 active enrollments for 592 clients across six demo projects.

CheckFindsFlaggedChecked
DQ01Name missing, unknown or refused17913
DQ02SSN missing or failing format rules68913
DQ03Date of birth missing or impossible14913
DQ04Veteran status missing for adults13709
DQ05Disabling condition missing21913
DQ06Household without exactly one head of household13726
DQ07Prior living situation missing25730
DQ08Exit destination missing (8, 9, 99, 30 or blank)65651
DQ09Exit date before entry date2651
DQ10Entry recorded more than 4 business days late94789
DQ11Exit recorded more than 4 business days late57651
DQ12Overlapping shelter or transitional housing stays10382
DQ13Possible duplicate client records12712
DQ14Shelter or outreach enrollment open over 90 days3186

The generator planted 12 duplicate client pairs, 10 overlapping stays and 2 exits keyed before entry. The run flagged all of them.

How it is built

The HMIS stays the system of record. The reporting database is rebuilt from each export. A trigger makes loaded export tables read-only, so corrections are made in the HMIS and arrive with the next export. Each load stores its reporting period and the SHA-256 hash of every source file.

Findings are tracked through to correction. Each flagged record carries a status (open, sent to agency, corrected in HMIS, accepted as is), and a second trigger logs every status change with a timestamp.

Indexes follow the checks. The overlap and duplicate checks are self-joins on person, date and identifier indexes; the report prints their query plans.

Backups are tested. Each run copies the database with SQLite's online backup API, runs an integrity check on the copy and compares every table's row count and content hash with the live database.