Drift API
The drift router provides access to the ML model drift detection system. Drift monitoring tracks whether the scoring model's predictions are diverging from real-world outcomes, indicating the model may need retraining.
Router namespace: drift
Source: src/server/trpc/routers/drift.ts
Procedures
| Procedure | Type | Access | Description |
|---|---|---|---|
getStatus | query | tenant | Get live drift status |
getHistory | query | admin | Get drift check history |
triggerCheck | mutation | admin | Force a manual drift check |
getStatus
Returns the current drift status from the ML sidecar. Includes the drift score, detection method, and whether the model is considered drifted.
drift.getStatus.queryOptions()
Input
None.
Response
{
"isDrifted": false,
"driftScore": 0.12,
"threshold": 0.25,
"method": "psi",
"lastChecked": "2026-03-20T14:30:00.000Z",
"featureDrifts": [
{ "feature": "industry", "score": 0.08, "drifted": false },
{ "feature": "employeeCount", "score": 0.31, "drifted": true }
]
}
| Field | Description |
|---|---|
isDrifted | true if overall drift score exceeds threshold |
driftScore | Aggregate drift score (0--1) |
threshold | Configured drift threshold |
method | Detection method ("psi" = Population Stability Index) |
featureDrifts | Per-feature drift breakdown |
Example
const trpc = useTRPC();
const { data: driftStatus } = useQuery(
trpc.drift.getStatus.queryOptions()
);
if (driftStatus?.isDrifted) {
console.warn("Model drift detected -- consider retraining");
}
getHistory
Returns historical drift check results with optional filtering by funnel stage. Results are ordered by most recent first.
drift.getHistory.queryOptions(input)
Access: Admin only
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
stage | string | No | -- | Filter by funnel stage name |
limit | number (1--200) | No | 50 | Maximum entries to return |
Response
[
{
"id": "dft_abc123",
"driftScore": 0.12,
"isDrifted": false,
"method": "psi",
"stage": null,
"checkedAt": "2026-03-20T14:30:00.000Z"
},
{
"id": "dft_def456",
"driftScore": 0.42,
"isDrifted": true,
"method": "psi",
"stage": "Decision",
"checkedAt": "2026-03-19T14:30:00.000Z"
}
]
Example
const trpc = useTRPC();
const { data: history } = useQuery(
trpc.drift.getHistory.queryOptions({ limit: 20 })
);
// Filter to only drifted checks
const driftedChecks = history?.filter((h) => h.isDrifted);
triggerCheck
Forces an immediate drift check via the ML sidecar. Normally drift checks run on a schedule, but this procedure allows admins to trigger one manually.
drift.triggerCheck.mutationOptions(options)
Access: Admin only
Input
None.
Response
{
"success": true,
"driftScore": 0.15,
"isDrifted": false
}
Example
const trpc = useTRPC();
const queryClient = useQueryClient();
const mutation = useMutation(
trpc.drift.triggerCheck.mutationOptions({
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: trpc.drift.getStatus.queryKey(),
});
queryClient.invalidateQueries({
queryKey: trpc.drift.getHistory.queryKey(),
});
},
})
);
mutation.mutate();
All drift procedures communicate with the Python ML sidecar. If the sidecar is unavailable, these procedures return a SERVICE_UNAVAILABLE error. Check GET /api/health to verify sidecar status.
Related Pages
- Feedback Loop API -- Conversion feedback that feeds drift detection
- Scoring API -- Scores affected by model drift
- Error Handling --
SERVICE_UNAVAILABLEwhen ML sidecar is down