How CDP segments recompute
The CDP event model defines the event stream and the CDP segments guide shows how to build an audience on it. This page is the frame between them: after an event lands, when does a segment actually move, and when does that move reach the surfaces downstream? The answer differs per surface — a dashboard membership badge, a journey trigger, an ad-audience sync, and a streaming destination each converge on their own cadence — so this page defines the lifecycle and the staleness guarantee for each. Read it once and every “is my segment current?” question reduces to a lookup in the table at the end.Section 1 — Event-time vs request-time attribution
A segment decision is never made on the request that ingested the event. WhenPOST /api/v1/cdp/track accepts an event, the request does exactly
three things: validate the payload against your tracking plan, append the
row to the tenant’s cdp_events table, and publish the event onto a
per-tenant pub/sub channel. The 200 tells you the ingest truth is durable
— nothing more. Privacy governance (suppression, erasure cascades) runs on
the same pipeline, covered in
Consent and suppression model.
Everything downstream — identity binding, segment membership, computed
traits, journey enrollment, destination delivery — runs after the
request, on workers that subscribe to that channel or sweep on their own
cadence. Two consequences operators should internalize:
- Batches, not the request, move segments. An event backdated by the
client still triggers a re-evaluate pass as soon as it lands; the
decision rides on the server-stamped arrival time, never on the
forgeable client
timestamp. - Failures defer, they never block ingest. A degraded worker skips an event and catches up on the batch tick; the ingest path itself keeps a clean 200 either way. Real-time is the fast path, never the only path.
Section 2 — The real-time re-evaluation pass
Within roughly a second of an acceptedtrack or identify event, Orbit
re-evaluates the one contact the event binds to against every
auto-refresh segment in the tenant — and touches nothing else:
- The pub/sub fan-out delivers the event to a subscriber that first
filters it: events with no resolved contact id skip (an anonymous,
pre-identify event cannot move membership; the first event after
identify catches up), and
page/screen/group/aliasevents skip (they do not change the segmentable contact row in a way the membership engine keys on — the batch tick converges them). - The contact is re-evaluated against the tenant’s auto-refresh segment definitions — the identical filter compiler the scheduled batch refresh uses, so real-time and batch never disagree on whether a contact matches.
- The fresh match set is diffed against the contact’s current membership rows, and only the crossings are applied: a segment the contact newly matches is entered, a segment it no longer matches is exited.
A guard prevents recursion: the
segment.entered / segment.exited
events this pass itself emits are skipped at the filter, so a crossing
never re-triggers the pass that produced it.
Section 3 — Scheduled re-enrichment of profile traits
Segments filter on two ingredient classes, and they drift on different cadences:- Behavioral facts (performed events, event counts) — re-evaluated per contact, near-instantly, by the pass above.
- Profile traits (the enriched attributes an operator’s segment filter references — industry, country, lifecycle stage) — refreshed on a daily sweep.
Section 4 — Streaming delivery: always-on destinations and the deliberate config-skip
Streaming delivery to external buses does not depend on a segment at all. A tenant’s configured Kafka topic or Kinesis stream receives every tracked event — the full CDP event stream, segment membership changes included — within tens of milliseconds of ingest, by subscribing to the same pub/sub fan-out the membership pass consumes. There is nocdp_events
polling and no segment-resolution gate between ingest and the bus.
The config resolution is deliberately fail-soft: per-tenant destination
config is cached for 30 seconds, and a transient failure to read it
(a pool reconnect, a failover blip) is classified as transient and the
event is skipped rather than retried hot or surfaced as an operator
alert. The next event for that tenant re-resolves the config fresh — no
bad state persists, nothing to be cleared. Expect single-event gaps
on the destination during a transient store blip; a sustained outage is a
different shape (consecutive failures surface on the destination’s
run-status, and a per-tenant dead-letter queue bounds loss against a
genuinely misconfigured bus).
Two deliberate design points to plan against:
- If you mirror audiences into your own downstream, do it off the stream,
not off the membership table —
segment.entered/segment.exitedare first-class events on it, and the membership rows the dashboard reads are a read-model over the same crossings. - Destination config edits (enable, credential swap) propagate to the delivery path within the 30-second cache window — expect a sub-minute warm-up, not a request-time effect.
Section 5 — The segment staleness model, per surface
Segments are real-time-ish, not instantaneous. Every auto-refresh segment has two recomputers that agree by construction — the per-contact real-time pass on the event stream (the fast path) and the scheduled batch refresh sweeping the tenant’s auto-refresh set (the backstop) — but each downstream surface holds its own staleness guarantee:page / screen / group / alias events and anonymous (pre-identify)
events carry no request-time membership effect: the real-time pass skips
them by design, and the scheduled tick converges them.
Section 6 — What this means for reads
Three practical rules operators should code and brief against:- Never read-your-own-write. A
track200 acknowledges the event; it does not carry any membership decision. Two immediate reads — one to ingest, one toGET /api/v1/cdp/segments— are not causally linked: the second can return the pre-event membership. Poll the segment list or the membership badge; don’t assert on the response of the first. - Plan downstream in hours, not seconds. A contact qualifying for a
segment is not the same as an ad platform’s custom audience containing
that contact — the sync destination runs on its own cadence after the
segment moves. If a campaign must act on a membership change now,
trigger off the
segment.enteredwebhook or a journey, not off an ad audience. page/screenevents do not refresh segments at the fast-path cadence. If your segment filters must react to them, the segments still converge — on the scheduled batch cadence, not per-event.
Section 7 — Relationship to the event model and accounts
The pieces this page draws on are defined elsewhere:- CDP event model — the append-only stream
the membership pass reads, the server-stamped arrival ordering it
trusts, and the identity binding that makes a
contact_idresolvable. - B2B accounts — the read-side projection the same event stream powers; group/account membership has the same read-after-ingest posture as segment membership.
- CDP segments guide — how to build the segments whose lifecycle this page describes.
- Async processing model — the platform-wide rule (request acknowledges, workers converge) the CDP pipeline is one instance of.
Cross-references
- CDP event model — the stream this lifecycle recomputes over.
- CDP segments — building the audiences.
- Async processing model — the platform async posture.
- Consent and suppression model — privacy governance on the same pipeline.
- Operator observability map — where worker and destination health surfaces for operators.
- Tenant isolation — each tenant’s stream and workers are isolated per tenant schema.