Most data classification schemes die in a spreadsheet. This guide shows how to implement classification so it actually works: a two-dimensional scheme of sensitivity tiers plus handling overlays, expressed as one taxonomy in three places (database metadata, a code attribute, and a documented inventory), and held in lockstep by a coverage test that fails the build. Once classification is machine-readable, it drives real controls: field masking, non-production obfuscation, retention, and erasure are written once against the label rather than re-implemented per table. We cover the scheme, the enforcement, the SQL Server and Azure infrastructure, and the controls classification unlocks. It is the technical backbone of data protection by design.
Why most data classification fails
Almost every organisation has a data classification policy. Very few have data classification that does anything. The policy names some tiers, a governance team maps a handful of systems, the document goes into a shared drive, and the code carries on with no idea which of its columns hold a child’s medical notes and which hold a product identifier.
The failure mode is always the same. Classification lives in a document, the system lives in code, and the two never meet. A developer adding a field has no signal that it is sensitive, no control fires differently because of the label, and six months later the spreadsheet is a work of fiction.
Classification that works has three properties the spreadsheet version lacks. It is machine-readable, so code and infrastructure can act on it. It is enforced, so it cannot silently fall out of date. And it drives real controls, so the label is load-bearing rather than decorative. The rest of this guide is how to build all three.
A classification scheme with two dimensions
A single sensitivity level is not enough, because two fields can be equally damaging to expose for entirely different reasons, and those reasons pull in different controls. The workable design uses two orthogonal dimensions.
Sensitivity tiers
The first dimension is a tier that records how damaging exposure would be. Four levels cover most systems:
- Public. Data that can be shared freely, such as a published article or a public price list.
- Internal. Non-personal operational data such as configuration or reference values, damaging only in aggregate.
- Confidential. Most personal and commercial data: names, contact details, account information.
- Restricted. The highest-risk categories: special-category data such as health, children’s data, financial instruments, and secrets.
Handling overlays
The second dimension is a set of overlays that record why a field needs care, and pull in specific handling. A field can carry more than one:
- Special-category data, meaning health, biometric, or other Article 9 data that needs a specific lawful condition.
- Children’s data, which raises the stakes on everything from consent to retention.
- Safeguarding data, such as welfare notes or background-check status.
- Financial-instrument data, such as a bank account and sort code.
- Secret, for credentials, keys, and tokens.
- Free text, for unstructured fields that might contain any of the above, so they default to the highest plausible tier.
The combining rule
The rule that ties the two dimensions together is that an asset takes the highest tier any of its fields or overlays demands. A table that is mostly confidential but holds one restricted column is a restricted table. This “highest tier wins” rule is what lets you reason about a whole record, a whole export, or a whole backup from the classification of its parts.
One taxonomy, three expressions, one enforcing test
The single most important implementation decision is to express the taxonomy once and represent it in three places that a test keeps in lockstep. This is what stops classification drifting.
One taxonomy, three expressions, one test
The coverage test fails the build if any of the three drift apart
Database metadata
Native sensitivity labels on each classified column.ADD SENSITIVITY CLASSIFICATION
Code attribute
A tag on each sensitive property, driving masking, blob tags, and obfuscation.[ClassifiedData(label, overlays)]
Documented inventory
A human-readable register of every classified column and its rationale.
Database metadata
The database is where engine-level tooling looks, so the classification has to live there. SQL Server and Azure SQL support native sensitivity labels applied with the ADD SENSITIVITY CLASSIFICATION statement. Each classified column gets a label, an information type such as Health, Financial, or Contact Info, and a rank from low to critical. These populate the sys.sensitivity_classifications system view.
Because a native label carries only one dimension, store the overlays alongside as an extended property on the column, for example a space-separated set of overlay codes. A small reusable procedure that idempotently adds or updates that extended property keeps the overlay handling consistent across every table.
Code attribute
The application needs the classification too, so it can drive redaction, export, and erasure. The pattern is a simple attribute on each sensitive property, for example a [ClassifiedData(label, overlays)] annotation carrying the tier and the overlay flags. The attribute exposes the label and overlay codes so the same object drives every classification-aware control, rather than each control keeping its own list of sensitive fields.
Documented inventory
The third expression is for humans: a register of every classified column, its label, its overlays, and the reason. Auditors, data protection officers, and new engineers read this. On its own a document rots, which is why the test matters.
The coverage test that fails the build
The mechanism that makes classification reliable is a bidirectional coverage test that runs on every push. It builds the data model, reads the database classification scripts, and asserts both directions:
- Every column classified in the database has a matching code attribute with the same label and overlays.
- Every property carrying the code attribute has a database classification entry.
A developer who adds a sensitive column without classifying it, or classifies it in one place but not the other, breaks the build. This is the difference between a classification policy and a classification contract. The document cannot drift from the code, because the test will not let it.
The Azure and SQL Server infrastructure
Classification is not only an application concern. The point of putting labels in the database engine is that infrastructure can act on them, which is where a lot of the compliance value comes from.
- SQL auditing can log the sensitivity rank of the data a query returned, so you have a record of who touched restricted data, not just who ran a query. Route the audit stream to a log analytics workspace for retention and alerting.
- Data discovery and classification scanners, including Microsoft Defender for SQL, read the labels to inventory sensitive columns and flag unclassified ones, giving you continuous coverage beyond the build-time test.
- Blob index tags carry the classification with stored files. When a document is uploaded, tag it with its label and overlays so storage-side tooling can find every restricted file without opening any of them.
- Transparent data encryption and encrypted, private object storage protect the classified data at rest as a baseline under everything above.
Deploy wiring that stays idempotent
Classification scripts should run as a distinct metadata phase of the schema deployment, after tables, indexes, and procedures exist. Guard them so they run only on engines that support sensitivity classification, and write them to be idempotent, because re-applying a label should overwrite cleanly rather than fail. A useful side effect of scripting classification against real columns is that renaming or dropping a classified column without updating its script breaks the deploy, which is another safety net against silent drift.
What machine-readable classification unlocks
The reason to do all this is that once classification is machine-readable, the controls that depend on it are written once against the label rather than re-implemented per table. This is where the investment pays back.
Field-level masking
Redaction reads the label and the caller’s permissions and decides whether to mask a field. Because the rule is driven by the classification, adding a new sensitive column brings it under redaction automatically once it is labelled, rather than requiring a change to every query that returns it.
Non-production obfuscation
A generic obfuscator can reflect over the classification attributes and blank every classified field, so a record copied to a test environment carries no real personal data. For imported legacy data, a deterministic anonymiser seeded from a stable hash produces realistic but fake values while keeping foreign keys consistent, so the system still behaves correctly on synthetic data. Either way, the classification is what tells the obfuscator which fields to touch.
Retention and erasure
Retention and erasure need to know which columns hold personal data so they can anonymise or delete it. Driving this from the classification means a retention sweep reaches every classified column, and a coverage test can even assert that every classified table is covered by a retention rule or an explicitly documented exemption. The retention and erasure guide covers that engine in depth.
Storage and blob discovery
Classified files carry their label as a blob index tag, so a data-loss-prevention or discovery tool can enumerate every restricted document across storage without reading content. Classification turns “where is our sensitive data” from a research project into a query.
Classifying deliberately, not everything
A common mistake is to over-classify, which is as damaging as under-classifying. If every column is restricted, nothing is, because the label stops carrying information and teams start ignoring it.
Classify the data that genuinely needs it: personal data, special-category data, safeguarding data, financial instruments, and secrets. Do not classify enumerations, status flags, surrogate keys, or foreign keys that carry no personal meaning. The goal is a scheme where a restricted label is a real signal that triggers real handling, not a blanket that everyone learns to look past.
There is one subtlety worth handling explicitly. When a requirement deliberately exposes classified data at a lower tier, for example a staff photo that is confidential being published to a public website, do not silently reclassify it. Keep the source at its true tier, model the exposure as a separate, revocable consent decision, and gate the public surface on that consent at serve time. The data is still what it is; only one rendered copy is public.
Where to start
If you are retrofitting classification into an existing system, or designing it into a new one, sequence it like this:
- Define the scheme. Agree the tiers and overlays, and write down the combining rule.
- Classify the highest-risk data first. Special-category, children’s, financial, and secret columns before anything else.
- Express it in the database and the code. Native sensitivity labels plus a code attribute, from the same taxonomy.
- Add the coverage test. This is what turns the scheme from documentation into a contract.
- Wire one control to the label. Masking or obfuscation is a good first, because it proves the classification is load-bearing.
- Turn on the infrastructure. SQL auditing, data discovery, and blob tags, so sensitivity is visible to your tooling.
Data classification is unglamorous, and it is the control that makes the others possible. Get it machine-readable and enforced, and masking, retention, erasure, and breach response all become tractable. Leave it in a spreadsheet, and none of them can be trusted. If you want classification designed into a build so it drives real controls from the start, book a consultation or read how we approach data protection by design.
Frequently asked questions
What is data classification in software terms?
What are the levels of a data classification scheme?
How do you stop a data classification scheme going out of date?
What are SQL Server sensitivity labels?
How does data classification drive redaction and erasure?
Where should data classification live, in the database or the code?
Related guides
Data Protection by Design: The Standard Features Every Compliant System Needs
Data protection by design is an engineering discipline, not a policy document. This guide sets out the standard software features every GDPR-compliant system needs, and how to build them in from the first line of code.
Data Subject Rights, Retention and Erasure: The Engineering
Subject access, portability, and the right to erasure are software features with statutory deadlines, not favours. This guide covers how to build them, including retention engines, crypto-shredding, and erasure that keeps the audit trail.
How Adaptive Learning Platforms Actually Work
Genuine adaptive learning is an architecture, not a feature: the item bank, learner model, sequencing engine, and feedback loop every real platform needs.