Building a Labour Law Compliance Engine: Modelling 10,000+ Rule Combinations for Automated Wage Calculation
A deep dive into Xrosters' rule engine architecture. How we modelled composable labour law rules, resolved conflicts, and built a real-time compliance checker that processes thousands of rule combinations per shift.
Why Compliance Is Hard
Australian labour law is not a single document. It's a hierarchy: the Fair Work Act, Modern Awards (122+ of them), enterprise agreements, individual contracts, and state-specific long service leave provisions. Each defines rules about pay rates, overtime, breaks, penalties, and conditions.
A single shift assignment can trigger rules from multiple sources simultaneously. Working a Saturday might invoke:
- The Saturday penalty rate from the Modern Award
- The overtime threshold from the enterprise agreement
- The minimum break requirement between shifts
- The casual loading if the employee is casual
- The public holiday rate if it's a holiday weekend
These rules compose, interact, and sometimes conflict. Building a system that evaluates all of them correctly, in real time, as a manager builds a roster — that's the challenge we faced with Xrosters.
The Rule Engine Architecture
Rules as Data, Not Code
The first decision: rules must be data, not hardcoded logic. If a penalty rate changes (and they do, every July), you update a data record, not deploy new code.
interface ComplianceRule {
id: string;
source: 'award' | 'enterprise_agreement' | 'contract' | 'legislation';
condition: RuleCondition;
effect: RuleEffect;
priority: number;
description: string;
}
interface RuleCondition {
employmentType?: ('casual' | 'part_time' | 'full_time')[];
dayOfWeek?: number[];
startTimeWindow?: { from: string; to: string };
hoursThreshold?: number;
ageThreshold?: number;
}
interface RuleEffect {
type: 'penalty_rate' | 'overtime_rate' | 'minimum_break' | 'maximum_hours' | 'loading';
multiplier?: number;
flatRate?: number;
hoursThreshold?: number;
}
Each rule is a declarative statement: "Under these conditions, apply this effect." The engine evaluates all applicable rules and resolves their combined effect.
Rule Composition
When multiple rules apply to the same shift, their effects compose. The composition model:
- Base rate — the employee's normal hourly rate
- Loadings — casual loading (25%) applies on top of base
- Penalty rates — Saturday (125%), Sunday (150%), public holiday (250%)
- Overtime — after 38 hours/week or 12 hours/day, whichever comes first
- Minimum engagement — casuals get paid minimum 3 hours per shift
The composition is multiplicative where the law says it should be (loadings × penalties) and additive where it shouldn't be. Getting this right required reading the actual legislation and modelling the math precisely.
Conflict Resolution
When two rules conflict (e.g., the Award says 150% on Sundays, but the enterprise agreement says 200%), the resolution principle is clear: the rule most beneficial to the employee wins. This is a fundamental principle of Australian labour law.
The engine implements this by sorting applicable rules by their financial impact on the employee and selecting the highest. This isn't a tiebreaker — it's a legal requirement.
Real-Time Evaluation
The most demanding requirement: compliance checks must happen in real time as the manager builds the roster. When they drag an employee onto a Saturday shift, the UI must immediately show:
- Whether the shift is compliant
- What it costs (including penalties)
- Whether it triggers any overtime thresholds
- Whether it violates minimum break requirements
To achieve this, the rule engine runs synchronously during roster editing. The evaluation pipeline:
- Collect — gather all rules that might apply based on the shift parameters
- Evaluate — check each rule's condition against the shift and employee
- Compose — combine the effects of all triggered rules
- Resolve — handle conflicts using the "most beneficial" principle
- Report — return compliance status, cost breakdown, and warnings
This happens in milliseconds. The manager sees the impact before the shift is committed.
Wage Computation
Roster compliance is one thing. Payroll is another. At the end of a pay period, the system must compute actual wages based on:
- Rostered shifts (what was scheduled)
- Actual attendance (via facial recognition clock-in/clock-out)
- Applicable rules at the time each shift was worked
- Adjustments for late arrivals, early departures, or missed breaks
The wage computation engine processes each clocked shift through the same rule evaluation pipeline used during rostering, but with actual hours instead of scheduled hours. The result: automated, compliant payroll without manual calculation.
What We Learned
Building a compliance engine taught us three things:
-
Domain knowledge is code. The hardest part wasn't the engine — it was understanding the labour law well enough to model it. We spent weeks reading Awards and legislation before writing a single line of code.
-
Rules are never as simple as they seem. "Time-and-a-half on Sundays" sounds simple until you discover the exceptions, the thresholds, the interaction with overtime, and the difference between "engaged to work" and "actually worked."
-
Real-time compliance changes behaviour. When managers see compliance warnings before committing a roster, they make better decisions. The system doesn't just catch errors — it prevents them.
Beyond Rostering
The rule engine pattern — declarative conditions, composable effects, conflict resolution — applies to any domain with complex regulatory compliance. Tax calculation. Insurance underwriting. Loan qualification. Anywhere the rules are complex, composable, and have legal consequences when they're wrong.
That's the kind of problem Ootaboo solves.
→ See the Xrosters case study — the rostering platform that implements this rule engine in production.
See the related product evidence.
This Deep Dive is grounded in a product with its own operating context and constraints.
See the Xrosters case study