Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
da3b0d0
Added time traveling use case tutorial
stktung May 20, 2025
4bbeb45
A few minor cosmetic update to the time travel tutorial
stktung May 20, 2025
e42113f
Added images and improved some representations in the auditing capabi…
stktung May 21, 2025
a7f7be8
Changed the terminologies around about synchronous vs asynchronous re…
stktung May 21, 2025
8d21d5c
Added more pre-compute vs on-demand read model narrative
stktung May 21, 2025
5179815
Added section about granularity of snapshot
stktung May 21, 2025
cbd753d
Updated the curl request and response for event api for clarity
stktung May 21, 2025
88b3057
Added missing message from script
stktung May 21, 2025
40b9694
Added time travel introduction
stktung May 22, 2025
0f84151
Added introduction content
stktung May 22, 2025
23742ce
Added hero image and improved clarity of article
stktung May 23, 2025
9b1e0a6
Updated title and header for better SEO for time travel
stktung May 23, 2025
3c96f58
Updated title and sidebar desc of older tutorials to improve seo
stktung May 23, 2025
fc15f74
Added og:image to time travel
stktung May 23, 2025
1e2ed13
Apply suggestions from code review
stktung May 23, 2025
e0f48e3
Applied fix as suggested by mark
stktung May 23, 2025
d2eb91c
Fixed path to og:image
stktung May 23, 2025
fce9655
Added outbox hero image
stktung May 23, 2025
f6a0fb1
Update docs/getting-started/use-cases/time-travel/tutorial-2.md
stktung May 23, 2025
c01928d
Apply suggestions from code review
stktung May 26, 2025
7f0b583
Refined points about denormalized data models
stktung May 26, 2025
095143c
Minor wording change
stktung May 26, 2025
9767608
Realigned denormalize info section
stktung May 27, 2025
7e882f8
Changed sidebar use case label from 'introduction' to 'overview'
stktung May 30, 2025
d58d850
Removed bracket at the end of comment
stktung May 30, 2025
2beb939
Update docs/getting-started/use-cases/time-travel/tutorial-5.md
stktung May 30, 2025
44bab38
Update docs/getting-started/use-cases/time-travel/tutorial-4.md
stktung May 30, 2025
399227f
Switched tutorial branch to main
stktung May 30, 2025
88aac04
Merge branch 'use-case-time-travel' of https://github.com/kurrent-io/…
stktung May 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions docs/.vuepress/configs/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ export const sidebarEn: EsSidebarOptions = {
expanded: false,
group: "Mix-and-Match Database",
children: [
"/getting-started/use-cases/mix-and-match-database/introduction.md",
{
text: "Overview",
link: "/getting-started/use-cases/mix-and-match-database/introduction.md"
},
{
text: "Tutorial",
collapsible: true,
expanded: false,
group: "Mix-and-Match Database Tutorial",
children: [
"/getting-started/use-cases/mix-and-match-database/tutorial-intro.md",
children: [
{
text: "Introduction",
link: "/getting-started/use-cases/mix-and-match-database/tutorial-intro.md"
},
"/getting-started/use-cases/mix-and-match-database/tutorial-1.md",
"/getting-started/use-cases/mix-and-match-database/tutorial-2.md",
"/getting-started/use-cases/mix-and-match-database/tutorial-3.md",
Expand All @@ -57,14 +63,20 @@ export const sidebarEn: EsSidebarOptions = {
expanded: false,
group: "Outbox Out-of-the-Box",
children: [
"/getting-started/use-cases/outbox/introduction.md",
{
text: "Overview",
link: "/getting-started/use-cases/outbox/introduction.md"
},
{
text: "Tutorial",
collapsible: true,
expanded: false,
group: "Outbox Tutorial",
children: [
"/getting-started/use-cases/outbox/tutorial-intro.md",
{
text: "Introduction",
link: "/getting-started/use-cases/outbox/tutorial-intro.md"
},
"/getting-started/use-cases/outbox/tutorial-1.md",
"/getting-started/use-cases/outbox/tutorial-2.md",
"/getting-started/use-cases/outbox/tutorial-3.md",
Expand All @@ -73,6 +85,36 @@ export const sidebarEn: EsSidebarOptions = {
]
}
]
},
{
text: "Time Travel",
collapsible: true,
expanded: false,
group: "Time Travel",
children: [
{
text: "Overview",
link: "/getting-started/use-cases/time-travel/introduction.md"
},
{
text: "Tutorial",
collapsible: true,
expanded: false,
group: "Time Travel Tutorial",
children: [
{
text: "Introduction",
link: "/getting-started/use-cases/time-travel/tutorial-intro.md"
},
"/getting-started/use-cases/time-travel/tutorial-1.md",
"/getting-started/use-cases/time-travel/tutorial-2.md",
"/getting-started/use-cases/time-travel/tutorial-3.md",
"/getting-started/use-cases/time-travel/tutorial-4.md",
"/getting-started/use-cases/time-travel/tutorial-5.md",
"/getting-started/use-cases/time-travel/tutorial-summary.md"
]
}
]
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
---
title: Introduction
title: Mix-and-Match Databases - Achieving Polyglot Persistence with KurrentDB
next: ./tutorial-intro.md
---

![](./images/use-the-right-database-for-the-job.png#light)

![](./images/use-the-right-database-for-the-job-dark.png#dark)

## Mix-and-Match Database

Modern applications often deal with diverse data access patterns that a single database can’t efficiently handle. That’s where you can leverage a database mix-and-match approach where different types of databases for different parts of your system can be used based on their strengths.

For example:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Part 1 - Setup and Initialize KurrentDB
prev: ./tutorial-intro.md
---

# Part 1: Setup and Initialize KurrentDB
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Introduction
title: Mix-and-Match Database Tutorial Introduction
prev: ./introduction.md
---

# Introduction
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions docs/getting-started/use-cases/outbox/introduction.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
title: Introduction
title: Solving Dual Writes with KurrentDB's Outbox, Out-of-the-Box
next: ./tutorial-intro.md
---

## Outbox Out-of-the-Box
![Solving Dual Writes with KurrentDB](./images/outbox-hero.png)

### Dual Write Problem
## Dual Write Problem
Without distributed transactions, operations that write to multiple resources are not atomic, potentially leading to inconsistencies in the system. This issue is commonly known as the dual write problem.

Although named "Dual Write," this pattern can involve writing to more than two resources. A common use case is updating a relational database and simultaneously sending a notification message via a message queue to another system.
Expand All @@ -22,7 +22,7 @@ Failure to write to one resource introduces inconsistency with the other. For in

Conversely, a failed database update paired with a successful message dispatch leads to downstream systems acting on non-existent data.

### Transactional Outbox Pattern
## Transactional Outbox Pattern
The transactional outbox pattern ensures consistency by writing business data and outgoing messages atomically within the same database transaction. A separate process later dispatches these messages to downstream systems, mitigating the dual write problem.

The outbox pattern promotes reducing the number of resources we write to, preferably to just one, and technically, to one transaction. This
Expand Down Expand Up @@ -53,7 +53,7 @@ Instead of directly managing an outbox table, another implementation of the outb

This approach avoids polling overhead and propagates updates with significantly lower latency. However, it relies on additional CDC tooling, increasing complexity if such tools aren't already part of the existing infrastructure. It also risks exposing the internal data model of the source tables, potentially creating undesirable coupling with other systems.

### Outbox Out-of-the-Box with KurrentDB
## Outbox Out-of-the-Box with KurrentDB

![Outbox with KurrentDB](./images/outbox-with-kurrentdb.png#light)

Expand All @@ -68,7 +68,7 @@ In effect, the stream is the outbox, out of the box.

The native subscription capabilities, such as persistent and catch-up subscriptions and connectors, act as cheap mechanisms for writing the glue code that sends messages to the other system.

### How to Approach the Dual Write Problem with KurrentDB
## How to Approach the Dual Write Problem with KurrentDB
1. Record each business change as an event and append it to a stream in KurrentDB, using the stream as the definitive source of truth.
2. Do not update other systems or read models directly as part of the same append operation.
3. Set up subscriptions to listen for new events in the stream.
Expand Down
1 change: 1 addition & 0 deletions docs/getting-started/use-cases/outbox/tutorial-1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Part 1 - Set up Codespaces
prev: ./tutorial-intro.md
---

# Part 1: Set up Codespaces
Expand Down
3 changes: 2 additions & 1 deletion docs/getting-started/use-cases/outbox/tutorial-intro.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: Introduction
title: Outbox Tutorial Introduction
prev: ./introduction.md
---

# Introduction
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 83 additions & 0 deletions docs/getting-started/use-cases/time-travel/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Time Traveling with KurrentDB
image: /getting-started/use-cases/time-travel/images/time-travel-hero.png
next: ./tutorial-intro.md
---

![Time Travel with KurrentDB](./images/time-travel-hero.png)

## What is Time Traveling?
Time traveling in data systems means being able to query or reconstruct your data as it existed at any point in the past. This is useful for many scenarios, such as auditing, debugging, compliance, and analytics.

| Use Case | Example |
|--------------------------------------|---------|
| Business process reconstruction | See the full lifecycle of a loan application, including every approval, rejection, and amendment, to resolve disputes or meet regulations |
| Point-in-time state diffing | Show exactly what changed in a customer’s profile or account settings between two points in time for support or compliance reviews |
| Simulation and what-if analysis | Simulate the impact of a pricing change or business rule adjustment by replaying all related product and sales events to see how outcomes would differ |
| Business event tracing | Audit the sequence of business events for a transaction (order placed, payment received, shipment sent, delivery confirmed) to verify SLAs or investigate complaints |
| Timeline-Based State Inspection | Let users view a timeline of how their account or order changed, with each step tied to a business event (like address updated, item added, return requested) |
| Temporal aggregate calculation | Track how total sales for a product changed over time by calculating monthly sales at the end of each month |

## Time Traveling with Traditional Approaches
Traditional databases struggle with historical queries because they are designed to store only the current state. Retrieving or reconstructing previous versions often requires extra mechanisms like audit logs, snapshots, or CDC with time-partitioned data lakes. These approaches add complexity, slow down queries, and may not always provide a complete or reliable view of historical data.

#### Audit Logs
Audit logs are a common approach in traditional databases for tracking changes. They record each modification as a new entry in a separate log table, typically including details such as who made the change, when it occurred, and what operation was performed.

**Advantages:**
- Provide a detailed record of changes.
- Can answer questions about who changed what and when.
- Useful for meeting regulatory requirements for tracking changes.

**Limitations:**
- Audit logs are separate from main data, risking inconsistencies if not commited together.
- Often capture only high-level operations.
- Gaps or missed events make it difficult to reconstruct past states.

#### Snapshots
Snapshots are another traditional method for preserving historical data. A snapshot captures the entire state of a table or dataset at a specific point in time, often on a scheduled basis (e.g., nightly or weekly), and stores it as a separate copy.

**Advantages:**
- Provide a complete view of data.
- Useful for restoring data after accident.
- Easy to implement without major changes to existing applications.

**Limitations:**
- Snapshots are taken infrequently.
- Storage requirements can be high.
- Snapshots lack a detailed audit trail of individual changes.

#### Change Data Capture (CDC) and Data Lake
Change Data Capture (CDC) is a technique that tracks and records changes (inserts, updates, deletes) in source databases and delivers them to downstream systems, often storing them in time-partitioned data lakes for analytics and historical queries.

**Advantages:**
- Captures detailed change events, enabling near real-time replication and analytics.
- Supports integration with data warehouses and lakes for large-scale historical analysis.
- Can be used to build audit trails and reconstruct state changes over time.

**Limitations:**
- CDC pipelines add operational complexity and require many moving parts
- Do not persist the actual change from the source, so lost events mean state can't be reliably reconstructed.
- Captured changes are usually low-level and technical, making business intent unclear.

## Time Traveling with KurrentDB

KurrentDB makes time travel simple by recording every change as an immutable, ordered event. This lets you accurately reconstruct any previous state, making historical queries, audits, and analysis straightforward without complex workarounds.

KurrentDB makes this possible because:

- It stores every change as an immutable event, preserving a complete and accurate history.
- It allows event streams to be replayed at any time for simulation, testing, and debugging—even far into the future.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how do we debug in the future?

- Its historical event log is naturally suited for regulatory and compliance needs, making audits and reporting straightforward.
- It supports outbox pattern out of the box, ensuring reliable delivery of historical events to downstream systems.
- It promotes events are modeled around business intent, providing clear context for historical queries.
- Events are small and focused, making them efficient to store and process.
- It handles storage, indexing, and pushing events natively, reducing the need for extra components in your time travel solution.

## How to Time Travel with KurrentDB

- **Store events in ordered streams:** Record every relevant change as an event in KurrentDB, ensuring events are stored in the order they occurred.
- **Replay events on-demand:** Replay all the relevant events from stream up to the desired timestamp or version.
- **Pre-compute state for efficiency:** For objects with long histories or frequent queries, you can periodically store snapshots of state. This reduces the number of events that need to be replayed for common queries.

KurrentDB’s approach makes time travel queries reliable, flexible, and efficient, supporting both detailed investigations and high-performance analytics.
34 changes: 34 additions & 0 deletions docs/getting-started/use-cases/time-travel/tutorial-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Part 1 - Set up Codespaces
prev: ./tutorial-intro.md
---

# Part 1: Set up Codespaces

In this part, you will start a GitHub Codespaces session in your browser.

::: info
GitHub Codespaces provides an instant and preconfigured development environment all within your browser. This environment contains all the tools and code to complete this tutorial. To learn more about Github Codespaces, [click here](https://github.com/features/codespaces).
:::

## Step 1: Set up Your Codespaces

1. Click the button below to initiate Codespaces and ensure following values are selected:

[![](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=time-travel&repo=951198039&skip_quickstart=true&devcontainer_path=.devcontainer%2Ftime-travel%2Fdevcontainer.json)


| Configuration Option | Selection |
|--------------------------------|----------------------|
| Branch | `main` |
| Dev container configuration | `Time Travel` |
| Region | Any value |
| Machine type | Any value |

Log in to GitHub if required.

2. Wait for your Codespace to build. This can take up to a few minutes.

::: tip
For this quickstart, you can safely ignore and close any Codespaces notifications that appear on the bottom right of the page.
:::
Loading