Hazardous waste
What I Learned Studying HP Codes
Notes on hazardous properties, evidence, and the discipline required when working through classification questions.
When I started mapping hazardous properties for digital waste tracking, I thought I was dealing with a list of codes.
HP1. HP2. HP3.
All the way through to HP15.
Simple enough, right?
It wasn’t.
The further I went, the more I realised that behind those seemingly simple codes sits an entire framework for understanding the hazardous characteristics of waste.
And, for a few days, I found myself going much deeper into that framework than I had originally anticipated.
Going beneath the HP codes
Hazardous properties are not simply labels attached to waste.
To understand how a waste stream may be classified, you can end up looking at information such as:
hazardous statements
hazard classifications
chemical constituents
concentrations
exposure routes
concentration thresholds
individual versus aggregated concentrations
testing
supporting evidence
and the relationship between different hazardous properties
For example, while mapping HP4 and HP6, I found myself translating regulatory logic into something a computer could actually evaluate.
A rule might effectively say that a particular constituent, with a particular hazard classification, needs to reach a particular concentration threshold before a hazardous property applies.
Other rules involve adding concentrations together.
Some apply to individual substances.
Some involve specific groups of substances.
And some hazardous properties have additional conditions or interactions that need to be considered.
At one point, my rule structure was beginning to look something like:
hazard statement → hazard classification → exposure route → concentration → threshold → aggregation → hazardous property
And that was the moment I had to step back.
Because I wasn’t just mapping data anymore.
I was beginning to build a chemical hazard assessment engine.
Understanding the complexity is not the same as exposing it
This became one of the most useful lessons from the exercise.
There is an important difference between:
understanding regulatory complexity
and
making the user interact with that complexity.
As a software builder, I need to understand why a hazardous property exists, what information can be relevant to it, and how the regulatory framework arrives at its conclusions.
But that does not automatically mean a waste operator should have to navigate every layer of that logic themselves.
The operator is dealing with a real waste movement.
They may have information provided with the waste, information from guidance, or results from their own testing.
They need to record the relevant information accurately and produce the data required for digital waste tracking.
The software should help them do that.
It shouldn’t turn every waste receipt into a chemistry examination.
Looking at what the digital system actually needs
This became even clearer when I looked closely at the Digital Waste Tracking API specification.
The data model is much more focused than the regulatory framework underneath it.
For hazardous waste, the system captures information such as whether the waste contains hazardous properties, the source of the component information, the hazardous property codes, and relevant component information such as names and concentrations.
That distinction was important for me.
The regulatory framework may be extremely detailed.
The digital reporting interface does not necessarily require every piece of that underlying reasoning to be entered manually by the operator.
That means there is a boundary.
There is the regulatory assessment.
And there is the digital reporting workflow.
Software operating around that workflow needs to understand both, without confusing the two.
The role of the software
This changed how I think about the compliance layer I am building.
The goal isn’t to recreate every page of regulatory guidance inside an application.
The goal is to build a regulatory-aware workflow around the information that actually needs to be captured and reported.
That means the software can focus on questions such as:
Is the required information present?
Is the information internally consistent?
Where did the component information come from?
Are the hazardous property codes valid?
Has the operator provided the information required for this particular situation?
Is the operator authorised to receive and handle this waste?
Can the information be translated into a valid digital waste tracking record?
And, importantly:
Can we show what happened and why?
That last part matters just as much as validation.
Compliance isn’t only about producing the correct output.
It is also about being able to understand how that output was produced.
What I learned from HP4 and HP6
Mapping individual hazardous properties was still extremely useful.
Working through HP4 and HP6 forced me to understand the difference between a hazard statement and a hazardous property.
A hazard statement such as an H-code describes a hazard associated with a substance.
An HP code describes a hazardous property of the waste.
Those aren’t interchangeable concepts.
The relationship between them is part of the assessment process.
That distinction sounds obvious when written down, but it becomes much more important when you try to represent the logic in software.
I also learned how quickly seemingly simple regulatory rules become complicated when you try to make them deterministic.
A sentence in guidance can become:
an input requirement
a matching condition
a threshold
an aggregation method
an exception
an outcome
and a record of why that outcome occurred.
That translation from human regulatory language into machine-readable logic is a fascinating problem in itself.
The rabbit hole was worth it
There was definitely a point where I wondered why I had voluntarily entered a world of concentration thresholds and hazardous-property rules.
But looking back, the rabbit hole was useful.
Not because I necessarily want to build a gigantic chemical classification engine.
Quite the opposite.
It helped me understand where such an engine would begin, how complicated it could become, and where that complexity may not belong in the operator experience.
Sometimes you need to understand the complicated version before you can confidently design the simple version.
Building software that respects the complexity
Digital waste tracking is often described as a data or technology transition.
But underneath the data are real waste movements, real businesses, real regulatory responsibilities and, in many cases, very complicated decisions about the waste itself.
The challenge for software isn’t to pretend that complexity doesn’t exist.
It is to handle complexity responsibly.
That means knowing what the software can validate.
Knowing what information the operator needs to provide.
Knowing what should come from existing documentation, guidance or testing.
Knowing when the software can make a deterministic check.
And knowing when a decision belongs with the appropriately qualified person rather than being invented by an algorithm.
That is probably the biggest thing I took away from mapping hazardous properties.
Good compliance software doesn’t necessarily remove regulatory complexity.
It puts that complexity in the right place.
And sometimes, building something simple requires going very, very deep first.
Nerdy technical side ---- HP4/HP6 rules example translated
Technical Notes: Mapping HP4 & HP6 into Machine-Readable Rules
What I was trying to do
I wanted to understand how the regulatory framework behind hazardous properties could be represented in software.
Rather than leaving the rules as human-readable guidance, I experimented with translating the regulatory logic into machine-readable rule definitions that a deterministic validator could evaluate.
The goal was not to make the operator understand the underlying calculations. The goal was to understand whether the regulatory logic could be represented clearly and consistently in software.
⸻
HP4 — Irritant
HP4 concerns waste that can cause skin irritation or eye damage.
The regulatory logic includes different hazard statements and concentration thresholds.
For example:
H314 / Skin Corr. 1A → HP4 pathway at 1%
H318 / Eye Dam. 1 → HP4 pathway at 10%
H315 / Skin Irrit. 2 + H319 / Eye Irrit. 2 → combined threshold of 20%
There is also an important interaction with HP8.
Where H314 corrosive substances reach the relevant 5% threshold, the waste is treated under HP8 (Corrosive) rather than HP4 for that pathway.
Turning that into a rule
Instead of hard-coding every threshold directly into Python, I represented the rule as data.
Conceptually:
rule_id
hazard statement
hazard classification
threshold
unit
aggregation method
outcome
For example:
H318
+
Eye Dam. 1
+
10%
+
sum
=
HP4 applies
The validator could then read the rule and evaluate the supplied constituents against it.
For the combined H315/H319 pathway, the rule needed to represent multiple hazard statements and classifications and use a grouped_sum aggregation.
That was my first real example of translating a sentence from regulatory guidance into something a computer could evaluate.
⸻
HP6 — Acute Toxicity
HP6 was where the exercise became much more complicated.
HP6 covers acute toxic effects following oral, dermal or inhalation exposure.
The rules contain different thresholds depending on the acute toxicity category and exposure route.
Examples include:
Oral
Acute Tox. 1 → 0.10%
Acute Tox. 2 → 0.25%
Acute Tox. 3 → 5%
Acute Tox. 4 → 25%
Dermal
Acute Tox. 1 → 0.25%
Acute Tox. 2 → 2.5%
Acute Tox. 3 → 15%
Acute Tox. 4 → 55%
Inhalation
Acute Tox. 1 → 0.10%
Acute Tox. 2 → 0.50%
Acute Tox. 3 → 3.50%
Acute Tox. 4 → 22.50%
The important part wasn’t just storing the numbers.
The system needed to understand that these thresholds belonged to different hazard categories and pathways.
For example, two substances shouldn’t simply be thrown into one total because they both happen to have an H-code associated with acute toxicity.
The classification matters.
That led to tests checking that:
a concentration below the threshold does not trigger HP6
a concentration exactly at the threshold does trigger HP6
concentrations within the same hazard category can be aggregated where the rule allows it
concentrations from different acute toxicity categories are not incorrectly combined
⸻
The machine-readable structure
I eventually simplified the HP4 and HP6 rulebooks so they followed a common structure.
The basic model became:
RULE
├── rule_id
├── hazard_statement(s)
├── hazard_classification(s)
├── threshold
├── aggregation
└── outcome
For example:
{
"rule_id": "HP4-H318",
"hazard_statement": "H318",
"hazard_classification": "Eye Dam. 1",
"threshold": {
"value": 10,
"unit": "%"
},
"aggregation": "sum",
"outcome": "HP4_APPLIES"
}
The important idea was that the rule itself is data.
The Python validator doesn’t need a separate if concentration >= 10 statement for every individual regulatory rule.
Instead, it can read:
threshold = 10%
and evaluate the supplied data against that rule.
⸻
Aggregation became a key concept
One of the things this exercise taught me was that “threshold” alone isn’t enough.
The software also needs to know how the concentration is evaluated.
I used three simple concepts:
Individual
Evaluate a qualifying constituent individually.
substance concentration >= threshold
Sum
Add qualifying concentrations together.
A + B + C >= threshold
Grouped sum
Add concentrations belonging to a defined group of qualifying hazards.
H315 + H319
↓
combined concentration
↓
20%
↓
HP4 applies
This allowed the same validator architecture to support different regulatory patterns without hard-coding every calculation.
⸻
The validator
The Python validator was then designed around the rulebook rather than around individual HP codes.
At a high level:
load rulebook
↓
identify HP code
↓
load rules
↓
match constituent to rule
↓
apply aggregation method
↓
compare against threshold
↓
return outcome
The result could contain information such as:
status: HP4_APPLIES
hp_applies: true
rule_id: HP4-H318
That creates something useful for an audit trail because the system can record which rule produced the result, rather than simply returning true or false.
⸻
Testing the translation
I didn’t want to assume that the machine-readable rules were correct just because the JSON looked right.
I created tests around boundary conditions.
For HP4, for example:
0.9% → does not trigger
1.0% → triggers
and:
9.9% → does not trigger
10.0% → triggers
I also tested the combined H315/H319 pathway and the HP8 precedence case.
For HP6, I tested the different oral, dermal and inhalation thresholds, as well as aggregation behaviour.
This exposed mistakes in the implementation.
That was actually one of the most useful parts of the exercise.
The tests weren’t just checking whether the code worked.
They were checking whether my interpretation of the regulatory rule had been translated correctly into software behaviour.
⸻
The important lesson
The biggest lesson wasn’t actually about HP4 or HP6.
It was about the boundary between regulatory intelligence and operator workflow.
The exercise showed me that a seemingly simple requirement such as:
“Does this waste have hazardous properties?”
can sit on top of a much more complicated regulatory framework.
I could build increasingly sophisticated logic around hazard statements, classifications, concentrations, thresholds and aggregation.
But that raised a more important product question:
Does the operator actually need to interact with all of that complexity?
Looking at the Digital Waste Tracking API made the distinction clearer.
DEFRA’s digital data model is concerned with information such as the hazardous-property codes, the source of component information, and relevant component details.
That means my software can understand the regulatory complexity without necessarily making the operator manually reproduce every step of the underlying assessment.
⸻
What this means for the product
This work has therefore become less about:
“Build a chemical hazard classification engine.”
and more about:
“Understand the regulatory logic deeply enough to build a simpler, safer workflow around it.”
The research into HP4 and HP6 is still valuable.
It gives the software a foundation for recognising regulatory relationships and validating information where appropriate.
But it also helped establish a boundary:
The software should support compliance decisions, not pretend that every regulatory decision can or should be automated.
That distinction is particularly important when dealing with waste classification, hazardous properties and operator responsibilities.
⸻
In one sentence
I translated regulatory language into machine-readable rules by breaking each requirement into structured components — the relevant hazard, classification, threshold, aggregation method and outcome — then built deterministic tests to verify that the software behaved consistently at and around those regulatory thresholds.
The surprising part was discovering that the deeper I went into the rules, the more important it became to make the final operator experience simpler, not more complicated.