The fastest way to build a compliance tracker is to pick one industry and hardcode it. The fastest way to be stuck with it is the same decision. Once a sector's vocabulary is in your table names and its categories are in your enums, the second sector is a fork, and the third is a rewrite.
Find the nouns that do not vary
Across every sector we looked at — dentistry, pharmaceuticals, food and beverage production, cosmetics, aerospace, precision engineering, chemicals, hazmat storage, veterinary care — the same four things keep appearing under different names:
- An asset: a serialised physical thing with a category, a location, an owner and a lifecycle.
- An obligation: anything time-boxed attached to it, with up to three dates that matter.
- A plan: the recurring commitment, such as calibration annually or inspection monthly.
- Evidence: what happened, and the certificate that proves it.
Note what is not on that list. Not device, not licence, not certificate — those are one sector's word for a general thing, and choosing one of them as a table name imports that sector's assumptions into every query written afterwards.
Push the difference into data
What actually differs between a dental lab and a machine shop is vocabulary, categories, which fields matter, how far ahead a renewal has to start, and what an inspector expects to be handed. All of that is configuration seeded per organisation:
- Categories and asset types.
- Obligation kinds, defined as rows rather than as an enum in the schema.
- Custom field definitions, with their types and validation.
- Default intervals and renewal lead times.
- Alert rules and escalation paths.
- Terminology labels, so the interface uses the customer's word.
- Report and export templates.
An industry pack is nothing more than a seeded set of those rows. It is a starting point, not a mode the product runs in — every value in it is editable on day one, and a customer who wants to start from the generic pack and build their own can.
The test for whether you got it right
Supporting a new sector should require no migration and no deploy. If it does, something sector-specific leaked into the schema or into a conditional, and the honest fix is to move it back out into configuration rather than to add another branch.
An enum of obligation kinds is a migration every time a customer has a kind you did not think of. A table of them is an insert.
The same rule applies to security claims and report templates. A page that promises one framework's compliance by name is the marketing equivalent of a hardcoded enum, and it ages just as badly.