Skip to content

Getting Started

Store your first event in 2 minutes

Let’s store your first event with DeltaBase. No theory. No patterns. Just see it work in 2 minutes.

  • Node.js 16+ (you probably have this)
  • 2 minutes

No API keys needed! We’ll run DeltaBase locally and you can visualize everything in the Studio.

First, let’s run DeltaBase locally. This gives you a full event store with a beautiful Studio for visualization:

Terminal window
npx @delta-base/cli dev

You should see:

┌────────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │██████╗ ███████╗██╗ ████████╗ █████╗ ██████╗ █████╗ ███████╗███████╗│ │
│ │██╔══██╗██╔════╝██║ ╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝│ │
│ │██║ ██║█████╗ ██║ ██║ ███████║██████╔╝███████║███████╗█████╗ │ │
│ │██║ ██║██╔══╝ ██║ ██║ ██╔══██║██╔══██╗██╔══██║╚════██║██╔══╝ │ │
│ │██████╔╝███████╗███████╗██║ ██║ ██║██████╔╝██║ ██║███████║███████╗│ │
│ │╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝│ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ Deltabase development environment is ready! │
│ │
│ API Server: http://localhost:8787 │
│ Studio UI: http://localhost:3000 │
│ │
└────────────────────────────────────────────────────────────────────────────┘

Open the Studio at http://localhost:3000 - this is where you’ll visualize your events!

In a new terminal (keep DeltaBase running), create your project:

Terminal window
mkdir deltabase-quickstart
cd deltabase-quickstart
npm init -y
npm install @delta-base/server

Before storing events, we need to create an event store. Create setup.ts:

import { DeltaBase } from '@delta-base/server';
const deltabase = new DeltaBase({
baseUrl: 'http://localhost:3000' // Your local DeltaBase instance
});
const managementClient = deltabase.getManagementClient();
async function setupEventStore() {
try {
// Create an event store called 'bank'
const eventStore = await managementClient.createEventStore({
name: 'bank',
description: 'Banking events for tutorial'
});
console.log('✅ Event store created:', eventStore.name);
console.log('📊 Check it out in Studio: http://localhost:3001');
} catch (error) {
if (error.message?.includes('already exists')) {
console.log('✅ Event store already exists');
} else {
console.error('❌ Failed to create event store:', error.message);
}
}
}
setupEventStore();

Run the setup:

Terminal window
npx tsx setup.ts

Now check the Studio - you should see your new event store!

Create index.ts:

import { DeltaBase } from '@delta-base/server';
const deltabase = new DeltaBase({
baseUrl: 'http://localhost:3000' // Your local DeltaBase instance
});
const eventStore = deltabase.getEventStore('bank');
async function main() {
const accountId = 'account-123';
console.log('💰 Making some transactions...');
// Store a deposit event
await eventStore.appendToStream(accountId, [{
type: 'money.deposited',
data: { amount: 100 }
}]);
// Store a withdrawal event
await eventStore.appendToStream(accountId, [{
type: 'money.withdrawn',
data: { amount: 30 }
}]);
console.log('📖 Reading transaction history...');
// Read all events back
const result = await eventStore.readStream(accountId);
console.log('Transaction events:', result.events);
// Calculate current balance from events
let balance = 0;
for (const event of result.events) {
if (event.type === 'money.deposited') {
balance += event.data.amount;
} else if (event.type === 'money.withdrawn') {
balance -= event.data.amount;
}
}
console.log(`💳 Current balance: $${balance}`);
console.log('🎉 You just did event sourcing!');
console.log('📊 View your events in Studio: http://localhost:3001');
}
main().catch(console.error);
Terminal window
npx tsx index.ts

You should see:

💰 Making some transactions...
📖 Reading transaction history...
Transaction events: [
{
type: 'money.deposited',
data: { amount: 100 },
streamId: 'account-123',
// ... other metadata
},
{
type: 'money.withdrawn',
data: { amount: 30 },
streamId: 'account-123',
// ... other metadata
}
]
💳 Current balance: $70
🎉 You just did event sourcing!
📊 View your events in Studio: http://localhost:3001

Now go to the Studio! Open http://localhost:3001 and:

  1. Select your ‘bank’ event store
  2. Click on “Events” in the sidebar
  3. See your events visualized in a beautiful table
  4. Click on “Streams” to see your ‘account-123’ stream
  1. You stored events - Facts about what happened (deposit $100, withdraw $30)
  2. You read them back - Perfect transaction history, permanently recorded
  3. You calculated state - Current balance ($70) comes from replaying all events

That’s event sourcing. Instead of storing current balance, you store what happened. The balance is calculated from the events.

  • Perfect audit trail - You can see every transaction that ever happened (check the Studio!)
  • Time travel - Calculate balance at any point in history
  • Never lose data - Events are immutable facts, they never get overwritten
  • Bank-grade reliability - Every penny is accounted for
  • Beautiful visualization - The Studio shows you exactly what’s happening

Try this - add another transaction and run it again. You’ll see the history grow in both your terminal and the Studio.

Let’s add a tiny bit of validation. Replace your main() function:

async function main() {
const accountId = 'account-123';
// Helper function to get current balance
async function getCurrentBalance() {
const result = await eventStore.readStream(accountId);
let balance = 0;
for (const event of result.events) {
if (event.type === 'money.deposited') {
balance += event.data.amount;
} else if (event.type === 'money.withdrawn') {
balance -= event.data.amount;
}
}
return balance;
}
console.log('💰 Depositing $100...');
await eventStore.appendToStream(accountId, [{
type: 'money.deposited',
data: { amount: 100 }
}]);
console.log('💰 Trying to withdraw $150...');
// Check if we have enough money
const currentBalance = await getCurrentBalance();
const withdrawAmount = 150;
if (currentBalance >= withdrawAmount) {
await eventStore.appendToStream(accountId, [{
type: 'money.withdrawn',
data: { amount: withdrawAmount }
}]);
console.log('✅ Withdrawal successful');
} else {
console.log(`❌ Insufficient funds. Balance: $${currentBalance}, Attempted: $${withdrawAmount}`);
}
const finalBalance = await getCurrentBalance();
console.log(`💳 Final balance: $${finalBalance}`);
}

Run it again. You’ll see the business rule in action - can’t withdraw more than you have!

You just learned the core of event sourcing:

  1. Store events (facts about what happened)
  2. Calculate state from events
  3. Use current state for business decisions

Ready for something more complex? Check out:

Event sourcing isn’t complicated. Events go in, state comes out. Everything else is just details.