Rebuild employee projections
Recomputes per-employee projections from scratch. Use this when a read-model looks out of sync with the underlying events.
What is a projection?
The app pre-computes several read-models per employee — the data the UI reads when you open a page. Each projection is built from events (time-off requests, timesheet submissions, terms changes…) and kept in sync as new events arrive. If a projection ever drifts (after a bad migration, a manual data fix, or a deploy that introduced a bug), rebuilding it from the source events restores it to a known good state.
Projections this job rebuilds
| Projection | What it backs |
|---|---|
| Employee search | The employee directory and search bar |
| Employment periods | Each employee’s resolved current and historical terms |
| Time-off employee projection | Planned, active, and used absences per employee |
| Time-bank balance | Account balances per employee |
| Accrual forecast | Forecasted upcoming accruals |
| Timesheet weekly projection | Per-week timesheet aggregates |
| Timesheet statements | Each employee’s pending/ready/submitted statements |
| Policy activity | Resolved activity per time-off policy per employee |
| Approvals inbox | The manager’s “to approve” list |
| Notification user view | The notifications feed per user |
How it works
- Loads the scope — by default, every employee in the workspace
- For each employee, runs each builder in turn — most builders simply replay the relevant events through the same handlers used in production
- For some projections, a second pass runs after every employee is rebuilt — e.g. the IsManager flag, which depends on every direct-report row being settled
Parameters
| Parameter | Description |
|---|---|
| Projection | The projection to rebuild. Defaults to all. Picking a single projection narrows the work — useful when you know which read-model is off |
| Employee ID | Optional. Rebuild only this employee’s projections |
| Org Unit ID | Optional. Rebuild every employee in this org unit and its descendants. Ignored when Employee ID is set |
When the scope is restricted (single employee or org unit), the post-rebuild-all step is skipped — those steps assume every employee was just refreshed.
Job results
| Metric | Description |
|---|---|
projection | The target that was rebuilt (all or a specific key) |
scope | all, employee:<id>, or org_unit:<id> |
success_count | Employees rebuilt without error |
error_count | Employees the rebuild failed on (see the run details for the per-employee errors) |
When to run
- After importing data from another system
- After fixing a malformed event with a migration
- When a single employee’s UI looks wrong (use Employee ID to scope to one)
- After an incident report that mentions one of the projections by name
Auto-trigger on backfill
When the worker starts up and finds any registered projection completely empty but employees exist, it schedules this job automatically. That’s an operational safety net for fresh deployments and restored backups.
Troubleshooting
| Issue | Solution |
|---|---|
| Run takes a long time | Rebuilding all projections for every employee is the most expensive option. Scope down to a single projection or a single org unit when you know what you’re trying to fix |
| Errors on a few employees | Open the job run details to see the per-employee errors. Often it’s a stale reference to a deleted entity that can be fixed with a targeted edit, then re-rebuild that single employee |
| Projection still looks wrong after rebuild | The rebuild replays events through the live handlers. If the handler itself has a bug, rebuilding won’t fix it — escalate to the developers |