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.
What you need
Section titled “What you need”- 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.
Start DeltaBase locally
Section titled “Start DeltaBase locally”First, let’s run DeltaBase locally. This gives you a full event store with a beautiful Studio for visualization:
npx @delta-base/cli dev
yarn dlx @delta-base/cli dev
pnpx @delta-base/cli dev
bunx @delta-base/cli dev
deno run -A npm:@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!
Create your project
Section titled “Create your project”In a new terminal (keep DeltaBase running), create your project:
mkdir deltabase-quickstartcd deltabase-quickstartnpm init -ynpm install @delta-base/server
mkdir deltabase-quickstartcd deltabase-quickstartyarn init -yyarn add @delta-base/server
mkdir deltabase-quickstartcd deltabase-quickstartpnpm initpnpm add @delta-base/server
mkdir deltabase-quickstartcd deltabase-quickstartbun init -ybun add @delta-base/server
mkdir deltabase-quickstartcd deltabase-quickstartdeno initdeno add @delta-base/server
Create an event store
Section titled “Create an event store”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:
npx tsx setup.ts
yarn dlx tsx setup.ts
pnpm dlx tsx setup.ts
bun run setup.ts
deno run --allow-net setup.ts
Now check the Studio - you should see your new event store!
Store some events
Section titled “Store some events”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);
Run it
Section titled “Run it”npx tsx index.ts
yarn dlx tsx index.ts
pnpm dlx tsx index.ts
bun run index.ts
deno run --allow-net --allow-env 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:
- Select your ‘bank’ event store
- Click on “Events” in the sidebar
- See your events visualized in a beautiful table
- Click on “Streams” to see your ‘account-123’ stream
What just happened?
Section titled “What just happened?”- You stored events - Facts about what happened (deposit $100, withdraw $30)
- You read them back - Perfect transaction history, permanently recorded
- 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.
Why this is powerful
Section titled “Why this is powerful”- 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.
Add some business logic
Section titled “Add some business logic”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!
What’s next?
Section titled “What’s next?”You just learned the core of event sourcing:
- Store events (facts about what happened)
- Calculate state from events
- Use current state for business decisions
Ready for something more complex? Check out:
- Banking System - Account management with proper commands
- Shopping Cart - Inventory, orders, and handling conflicts
- Debug Any Bug - Time travel debugging in action
Event sourcing isn’t complicated. Events go in, state comes out. Everything else is just details.