Docs

Concepts

Understand facts, definitions, evaluation, derived state, and delivery in Kite.

Kite is an event-driven Customer Success as Code engine. Product behavior enters as facts; versioned TypeScript definitions explain what those facts mean; the state engine computes what is true for each customer now.

events + current traits + configuration
                  |
                  v
             state engine
                  |
                  v
 lifecycle, journeys, segments, health, rule logs, and emissions

Customer Success as Code

Activation, risk, and health are product logic. In Kite, that logic lives in source control rather than hidden dashboard settings.

This makes definitions:

  • explicit: each outcome has concrete conditions;
  • reviewable: changes appear in pull requests;
  • versioned: deployed snapshots are immutable and auditable;
  • testable: events can be evaluated locally or in test;
  • replayable: retained history can be recomputed under a pinned version;
  • explainable: state changes retain their trigger and rule context.

Configuration deployment changes interpretation; it does not rewrite raw product history.

Facts and interpretation

Kite separates what happened from what it means.

LayerExampleBehavior
Eventreport.exported at a specific timeImmutable historical fact
Traitplan: "growth"Current customer attribute
DefinitionThree exports complete an outcomeVersioned interpretation
Derived stateJourney complete, health 82Computed result

Events have occurrence timestamps and can be replayed. Traits are shallow-merged current state; they are not timestamped historical facts. During recompute, current traits apply across the retained event history.

See Identity and event taxonomy before choosing IDs, traits, and event contracts.

One customer boundary

A Kite customer is normally one account, workspace, or tenant identified by customerId. Every event, trait update, and derived state is scoped to that ID, project, and environment.

Kite does not merge aliases or infer a user-to-account hierarchy. Choose a stable customer boundary in the source system and use it consistently across producers.

Configuration primitives

The primitives answer different questions and should not be treated as interchangeable.

Lifecycle

Lifecycle answers: Which one stage is the customer in?

States are mutually exclusive. A customer starts in initialState; matching enteredWhen conditions transition it to another state. exitWhen returns to the previous valid state, and a terminal state is not left automatically.

Use lifecycle for durable stages such as new, trial, activated, or cancelled, not for every temporary operational label.

Journeys

Journeys answer: How far has the customer progressed through an ordered outcome?

A journey starts from a condition, advances required steps in order, can complete optional steps opportunistically, and may expire. Completed and expired instances do not restart automatically.

Use journeys for onboarding, implementation, adoption, or renewal paths with identifiable milestones.

Segments

Segments answer: Which non-exclusive cohorts match now?

A customer can belong to many segments simultaneously. Membership is recomputed from lifecycle, health, events, traits, and other conditions when relevant triggers occur.

Use segments for queues such as at_risk, high_intent, or expansion_candidate.

Health

Health answers: What continuous score summarizes selected behavior?

Weighted components produce a current score from event frequency, feature adoption, inverse event counts, or deterministic custom formulas. Health is an explainable summary, not a prediction.

Only configured event, schedule, or manual triggers recompute health. Time does not update a score without evaluation.

Rules

Rules answer: When this trigger occurs and these conditions are true, what action follows?

Rules run on matching events, journey changes, or schedules. A passing rule can transition lifecycle, add a customer to a segment, or emit a named signal. Each evaluation produces a rule log with pass or skip.

Signals and emissions

An emission is a named internal timeline event produced by lifecycle, journey, segment, or rule behavior. A matching webhook can deliver that event externally.

Declarative defineSignals definitions register signal IDs and detection metadata. Automatic first-occurrence and average-based signal detection is not currently executed by the state engine; rules can emit registered signals explicitly.

Shared conditions

Lifecycle, journeys, segments, and rules share a composable condition language:

{
  all: [
    { lifecycle: 'trial' },
    { eventCount: { event: 'feature.used', days: 7, min: 3 } },
    { not: { traits: { plan: 'free' } } },
  ],
}

Conditions describe truth, but evaluation still needs a trigger. For example, inactivity becomes true as time passes, but state changes only when scheduled or event/recompute processing evaluates that condition.

Evaluation model

For each event, Kite updates facts and evaluates dependent state in a deterministic sequence. The engine can process lifecycle, journey progress, matching rules, health triggers, and segment membership from the same event.

The important contract is not a specific internal call order; it is that the same inputs produce the same result:

same retained events
+ same current traits
+ same config version
+ same evaluation time
= same recomputed state

Events are ordered by occurrence timestamp and then event ID during recompute. Custom health formulas cannot use external bindings or nondeterministic values such as Date.now() and Math.random().

Current state, history, and timeline

These records serve different purposes:

RecordPurpose
Raw eventsImmutable product facts used for replay
Current stateFast answer to what is true now
Lifecycle and rule historyExplanation of transitions and evaluations
Timeline eventsNamed operational facts and emissions
Webhook deliveryAt-least-once transport of eligible timeline events

Recompute rebuilds derived state from retained raw events, but it does not make every history type equivalent. It may also append corrective emissions without deleting older timeline rows. See Backfill and recomputation for exact persistence behavior.

Idempotency

Retries must not duplicate product activity. A track idempotency key is scoped to project and environment.

  • Same key and canonical payload: return the original event as a duplicate.
  • Same key with a different customer, event, properties, or timestamp: return 409 IDEMPOTENCY_CONFLICT.
  • Conflict inside a batch: reject the whole batch atomically.

The Node.js SDK generates keys when retries are enabled. Supply a stable business key when the source operation already has one so deduplication also works across processes.

Webhook idempotency is separate: receivers deduplicate the stable Kite-Event-Id because delivery is at least once.

Configuration versions

The CLI compiles authored TypeScript into a stable snapshot. Each deployment creates an immutable version for one environment.

source files -> validate -> compiled snapshot -> test version -> live promotion

Promotion copies the exact stored test snapshot to live; it does not recompile local source. Rollback activates an existing version for future evaluation. Neither operation automatically recomputes existing customers.

See CI/CD and environment delivery for the release workflow.

Test and live

test and live isolate:

  • API keys;
  • customer identities and event history;
  • active configuration versions;
  • computed state and webhook subscriptions.

Keys encode the environment with kt_test_ or kt_live_. Develop and exercise models in test, then promote an immutable tested version deliberately.

Local, test, and live

ModeUsePersistence
kite devFast event-to-state feedbackIn-memory and disposable
testShared integration and historical impact testingPersistent, isolated cloud data
liveProduction evaluation and deliveryPersistent production data

Local state resets when kite dev stops. A successful local result proves model behavior, not cloud authentication, billing, workers, or webhook delivery.

Next steps

  1. Build a local model with the 5-minute quickstart.
  2. Learn each field in the Config Reference.
  3. Choose stable facts with Identity and event taxonomy.
  4. Model one outcome with Activation, churn, and expansion.

On this page