Skip to main content

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

ProcedureTypeAccessDescription
getStatusquerytenantGet live drift status
getHistoryqueryadminGet drift check history
triggerCheckmutationadminForce 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 }
]
}
FieldDescription
isDriftedtrue if overall drift score exceeds threshold
driftScoreAggregate drift score (0--1)
thresholdConfigured drift threshold
methodDetection method ("psi" = Population Stability Index)
featureDriftsPer-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

FieldTypeRequiredDefaultDescription
stagestringNo--Filter by funnel stage name
limitnumber (1--200)No50Maximum 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();
ML Sidecar Required

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.