History and versioning
Kessel maintains a complete version history of every resource representation. Each time a service reports a resource, Kessel creates a new immutable version rather than overwriting the previous state. Because Kessel never overwrites data, you get a full audit trail of how resources evolve and reliable change detection for event publishing.
Understanding the versioning system is essential for interpreting resource state, debugging integration issues, and understanding how Kessel detects changes.
Why Version History?
Section titled âWhy Version History?âKesselâs version tracking helps with:
Audit Trail â Every change to a resource is preserved as an immutable snapshot, providing a complete history for compliance, debugging, or forensic analysis.
Change Detection â Kessel compares the current version with the previous version to determine what changed and emit appropriate events to Kafka.
Lifecycle Tracking â Generation numbers distinguish resource resurrections (delete â recreate) from continuous updates.
No Overwrites â Representations are never modified in place. Each ReportResource call creates a new version, ensuring past states remain queryable.
Four Types of Version Numbers
Section titled âFour Types of Version NumbersâKessel tracks resource evolution using four distinct version fields:
1. CommonVersion
Section titled â1. CommonVersionâScope: Shared across all reporters
Increments: When common representation data is provided
Purpose: Tracks versions of shared resource attributes
The CommonVersion increments by 1 each time a reporter includes common representation data in a report (starting from 0). When no common data is provided, CommonVersion remains unchanged.
CommonVersion progression:
stateDiagram-v2
[*] --> 0: Report with common data
0 --> 0: Report without common data
0 --> 1: Report with common data
1 --> 2: Report with common data
This ensures CommonVersion always increments monotonically across the resourceâs lifetime, regardless of which reporter provides the common data or whether some reports omit it.
2. RepresentationVersion
Section titled â2. RepresentationVersionâScope: Per-reporter representation
Increments: Every ReportResource call
Purpose: Tracks individual data snapshots for a specific reporterâs view of the resource
Each time a reporter calls ReportResource, Kessel increments the RepresentationVersion by 1, even if the payload data is identical. This monotonically increasing counter provides a total ordering of all reports from that reporter.
RepresentationVersion progression:
stateDiagram-v2
[*] --> 0: Report
0 --> 1: Report
1 --> 2: Report
3. Generation
Section titled â3. GenerationâScope: Per-reporter lifecycle
Increments: When a tombstoned resource is resurrected
Purpose: Distinguishes delete/recreate cycles from continuous updates
When a resource is deleted (tombstoned) and then re-reported, the Generation number increments and the RepresentationVersion resets to 0. This allows Kessel to track how many times a resource has been deleted and recreated.
Generation progression:
stateDiagram-v2
[*] --> 0: Create
0 --> 0: Update
0 --> 0: Delete (tombstone)
0 --> 1: Report after delete
1 --> 1: Update
1 --> 1: Delete (tombstone)
1 --> 2: Report after delete
Use case: Detect when a cluster was deleted and a new cluster with the same name was created later, preventing misattribution of historical data.
4. ReporterVersion
Section titled â4. ReporterVersionâScope: Reporter-supplied metadata
Increments: Manually set by the reporter (optional)
Purpose: Opaque metadata for reporterâs own versioning scheme
The ReporterVersion is a string field supplied by the reporter in RepresentationMetadata.reporter_version. Kessel stores this field as-is without interpreting or validating it.
Use case: A reporter tracks its own data schema evolution (e.g., "v2.1.0") and includes it in the payload for downstream consumers to detect schema changes.
Version Increment Logic
Section titled âVersion Increment LogicâReportResource Flow
Section titled âReportResource Flowâflowchart TD
Start([ReportResource called]) --> Load[Load current version]
Load --> CheckTombstone{Was resource<br/>tombstoned?}
CheckTombstone -->|Yes| IncrGen[Increment Generation<br/>Reset RepresentationVersion to 0]
CheckTombstone -->|No| IncrVer[Increment RepresentationVersion by 1]
IncrGen --> CheckCommon{Common data<br/>provided?}
IncrVer --> CheckCommon
CheckCommon -->|Yes| IncrCommon[Increment CommonVersion]
CheckCommon -->|No| Done
IncrCommon --> Done([Done])
DeleteResource Flow
Section titled âDeleteResource Flowâflowchart TD
Start([DeleteResource called]) --> Tombstone[Mark resource as tombstoned]
Tombstone --> IncrVer[Increment RepresentationVersion by 1]
IncrVer --> End([Done])
Event Type Determination
Section titled âEvent Type DeterminationâKessel determines which event type to emit based on the API called and whether the resource already exists in the database.
flowchart TD
Start([API called]) --> CheckAPI{Which API?}
CheckAPI -->|ReportResource| CheckExists{Resource exists<br/>in DB?}
CheckAPI -->|DeleteResource| Deleted[Emit 'deleted' event]
CheckExists -->|No| Created[Emit 'created' event]
CheckExists -->|Yes| Updated[Emit 'updated' event]
Created --> End([Done])
Updated --> End
Deleted --> End