article · 2026-05-13 · ~5 min · 2018-01-01 – 2020-03-12

You called 311. Then what?

Property and blight complaints land at 311. Violation notices come from L&I. Where do the two records line up across the city — and where do they diverge?

Two of the city's records — Philadelphia's 311 service requests and its License & Inspections violations — sit on either side of a familiar civic question. A resident calls 311 to report a vacant building, an unpermitted construction site, an unsafe stairwell. L&I, separately, decides whether a violation gets cited. Both records are public; both are spatial; both can be sliced by zip code. Whether they tell the same story about a neighborhood is another matter.

The map

Couldn't load enforcement-gap data at build time — try the live L&I dataset instead.

The ranking

Why this isn't an accountability story

It's tempting to read a high ratio as "the city is enforcing here" and a low one as "the city is ignoring here." Don't. The 311 record and the L&I record measure different things: 311 is a record of calls, with all the reporting bias that comes with it — call rates can vary between zips for reasons that have nothing to do with underlying conditions, and the 311 dataset on its own can't separate "more problems" from "more callers." L&I is a record of citations, which can issue from inspections that have nothing to do with 311. Two zips can have very different ratios because their residents call at different rates, or because L&I happens to run a sweep through one of them, or because the mix of sub-categories within "property/blight" differs.

The right way to read this map is as a co-occurrence pattern, not a pipeline. It shows where the two records sit on top of each other and where they don't. Closing that gap — turning a co-occurrence into a pipeline — is the kind of question this data alone can't answer. It would need a parcel-level join (which the two tables can support but only fragilely), or sub-category breakdowns within "property/blight," or a model that controls for reporting bias by zip. None of those are what's shown above.

Data Sources

Primary datasets: Philadelphia 311 service-and-information requests (public_cases_fc) and L&I Violations, both via phl.carto.com. Window: 2018-01-01 – 2020-03-12. Frozen at deploy (2026-05-13).

Queries: enforcementGapSql('2018-01-01', '2020-03-12') — a single Carto query joining the top-20 zips by property/blight 311 volume with their L&I violation counts in the same window. Defined in src/lib/data/datasets/li-violations.ts.

Methodology & caveats: The ratio is violations per 100 complaints in the same zip and time window; it is not a per-complaint enforcement rate — L&I cites from multiple channels independent of 311. The window ends at the Carto snapshot for L&I, which appears to have paused in March 2020. "Property and blight" is the 311 service-type filter applied inside enforcementGapSql; the L&I side is everything in the violations table for the matching zip and window. For the full caveat list, see how we read the data.