Přeskočit na hlavní obsah

Segments

Segments are saved player filters. A segment is defined as a tree of trait + event conditions; materialised as a set of player_ids in players.segment_ids[]. Campaign fan-out joins on the GIN-indexed array — fast even on 1M-player tenants.

Definition shape

{
"operator": "AND" | "OR",
"conditions": [
{ "type": "trait", "field": "total_deposited", "op": ">", "value": 100000 },
{ "type": "trait", "field": "kyc_status", "op": "=", "value": "verified" },
{
"type": "event",
"event": "bet_settled",
"window": { "kind": "rolling", "days": 7 },
"aggregation": "count",
"op": ">=",
"value": 5
},
{
"operator": "OR",
"conditions": [
{ "type": "trait", "field": "current_tier_code", "op": "=", "value": "gold" },
{ "type": "trait", "field": "current_tier_code", "op": "=", "value": "platinum" }
]
}
]
}

Trait conditions evaluate against the players row (Postgres). Event conditions evaluate against raw_events in ClickHouse with a rolling time window. Groups can nest — operators build complex segments by combining AND/OR.

Allowed trait fields

external_id, email, phone, telegram_id,
status, kyc_status, kyc_level, current_tier_code,
default_currency_code, timezone,
total_deposited, total_withdrawn, total_wagered, total_won, ggr,
bet_count, session_count,
churn_score, ltv_predicted,
first_seen_at, last_seen_at, last_bet_at, last_deposit_at,
created_at,
rg_self_excluded

Plus vertical_activity.casino.bet_count and similar for sportsbook (read from JSONB).

Allowed operators

  • Equality: =, !=
  • Numeric: >, >=, <, <=
  • Set: in, not_in (with array value)
  • String: contains, starts_with
  • Existence: exists (no value)

Refresh strategies

StrategyWhen membership updates
on_demandManual POST /v1/segments/:id/refresh only
scheduledCron (default daily)
realtimeStream-processor calls /v1/internal/recompute-player-segments after every player attribute mutation; sweeper closes the gap with a 30s catch-up cycle

realtime is the default for new segments. Set via the Admin UI or PATCH /v1/segments/:id { refresh_strategy: "realtime" }.

Sample preview

The segment editor shows a live count + 10-row sample as you build the condition. Counts are estimates (use the /v1/segments/:id/refresh endpoint to get exact numbers + materialise membership).

Segment templates

Built-in templates for common patterns: "high rollers", "churn risk", "first-deposit declined", "sportsbook bettors", "VIP candidates". Pick + tweak; saves the typed shape with a name.

Performance notes

  • Trait-only segments compile to a single Postgres WHERE fragment + are evaluated in O(rows scanned) via the indexes on players.{tenant_id, last_seen_at, kyc_status, current_tier_code, …}.
  • Event-aggregation segments hit ClickHouse with a tenant + time-window filter — the columnar engine + ordering on (tenant_id, project_id, player_id, timestamp) keeps this fast even for 100M-event tenants.
  • Membership materialisation is UPDATE players SET segment_ids = ? per affected row — touched rows are typically <1% of the player table.