All Deep Dives

Building a Labour Law Compliance Engine: Modelling 10,000+ Rule Combinations for Automated Wage Calculation

How Xrosters represented pay conditions as data, combined applicable rules and showed potential breaches during roster editing, and the design behind its rule engine and wage calculations.

· 10 min read

Why Compliance Is Hard

Australian labour law is not a single document. It's a hierarchy: the Fair Work Act, Modern Awards, 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

Several rules can apply to the same shift, and their effects may conflict. Xrosters needed to evaluate the configured rules during roster editing and show the manager both warnings and pay consequences.

The Rule Engine Architecture

Rules as Data, Not Code

The first decision: rules must be data, not hardcoded logic. When a configured rate changes, it can be updated as a data record without deploying 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 model included the following example conditions. Rates and thresholds need to be configured for the applicable employment instrument; these examples are not a universal schedule of Australian pay entitlements:

  1. Base rate — the employee's normal hourly rate
  2. Loadings — casual loading (25%) applies on top of base
  3. Penalty rates — Saturday (125%), Sunday (150%), public holiday (250%)
  4. Overtime — after 38 hours/week or 12 hours/day, whichever comes first
  5. Minimum engagement — casuals get paid minimum 3 hours per shift

Each rule needs to specify how it combines with the others. Working that out requires checking the applicable conditions and testing the calculation; a generic formula cannot establish legal compliance.

Conflict Resolution

This version of Xrosters resolved conflicting configured rules by selecting the outcome most beneficial to the employee. For example, it compared the financial impact of two Sunday-rate rules and selected the higher amount.

That describes the engine's conflict policy. It does not establish which Award, agreement or statutory provision applies. Those questions must be resolved when maintaining the rule set.

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:

  1. Collect — gather all rules that might apply based on the shift parameters
  2. Evaluate — check each rule's condition against the shift and employee
  3. Compose — combine the effects of all triggered rules
  4. Resolve — handle conflicts using the "most beneficial" principle
  5. Report — return compliance status, cost breakdown, and warnings

This happens in milliseconds. The manager sees the impact before the shift is committed.

Wage Computation

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. This produces a wage calculation from the configured rules and attendance records. Its accuracy depends on those inputs and on keeping the rules current.

What We Learned

Maintaining the rule model was as important as implementing the evaluator:

  1. Domain knowledge is code. We needed to understand the applicable pay conditions before we could represent them as data. We spent weeks reading Awards and legislation before writing a single line of code.

  2. 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."

  3. Real-time compliance changes behaviour. Warnings during roster editing give managers a chance to revise a shift before committing it.

Beyond Rostering

A similar rule model can be useful in tax calculation or insurance underwriting, where several conditions affect an outcome. The evaluator is only part of the work: the applicable rules and their interactions still need domain expertise and ongoing review.

→ See the Xrosters case study — the previous rostering product behind this rule engine.

Read what the product needed to do, what we built and its current status.

See the Xrosters case study