Source data changes daily; rebuilding the entire graph for one updated document is an engineering failure. Incremental refresh applies targeted mutations only to the impacted subgraph.
refresh_pipeline:
source_event: policy_updated
impacted_entities: { strategy: 'entity index by doc_id', expected: ['Policy P-12', 'RefundRule'] }
tasks: [re-extract changed doc, re-link aliases, invalidate impacted community summaries]
sla: { max_staleness_minutes: 20 }
The pipeline has three moving parts: (1) map the changed document to the entities it touches via a doc→entity index, (2) re-extract and re-canonicalise just those entities/edges, (3) invalidate the community summaries built on them — a forgotten summary is how stale answers survive even after the underlying chunk was fixed.
Freshness is an SLA, not a vibe. max_staleness_minutes makes 'how current is the graph?' measurable and alertable. Tightening it costs infrastructure (more frequent re-extraction), so it's a deliberate trade, not a default.
Plan for failed refreshes. A refresh event can fail mid-way, leaving the graph partially updated. You need a backfill/replay step driven by the event log so a dropped event doesn't silently leave a pocket of stale data — and monitoring for refresh skew between source events and what the index actually reflects.