Unique username with DCB
Global uniqueness without sagas, using a read and a conditional append
Let’s build a registration flow where usernames are globally unique. No sagas. No compensation. Just DCB.
The naive version is “read if taken, then append if not.” Two requests can both read “free” and both insert. DCB closes that hole: you read tagged events up to a position, then append only if nothing matching slipped in after that position.
Request A Request B │ │ ├ readByQuery ──▶ empty │ │ ├ readByQuery ──▶ empty │ │ ├ append(condition) ──▶ OK │ │ ├ append(condition) ──▶ FAIL ▼ ▼ UserRegistered "username taken"What you will build
Section titled “What you will build”- A
UserRegisteredevent with ausername:tag - A DCB read that checks for collisions
- A conditional append that enforces uniqueness
Step 1: Define the event
Section titled “Step 1: Define the event”type UserRegistered = { type: 'UserRegistered'; data: { userId: string; username: string; }; tags: string[];};Step 2: Build the tag
Section titled “Step 2: Build the tag”const tag = `username:${username.toLowerCase()}`;Step 3: Read by query
Section titled “Step 3: Read by query”const query = { items: [ { types: ['UserRegistered'], tags: [tag], }, ],};
const { events, lastPosition } = await eventStore.readByQuery({ query, after: 0,});If events.length > 0, the username is already taken.
Step 4: Append with condition
Section titled “Step 4: Append with condition”const event: UserRegistered = { type: 'UserRegistered', data: { userId, username }, tags: [tag],};
await eventStore.append([event], { failIfEventsMatch: query, after: lastPosition,});If someone else registers the same username after you read, the append fails. That is the boundary doing its job.
Step 5: Handle conflicts
Section titled “Step 5: Handle conflicts”import { isAppendConditionError } from '@delta-base/server';
try { await eventStore.append([event], { failIfEventsMatch: query, after: lastPosition, });} catch (error) { if (isAppendConditionError(error)) { throw new Error('Username already taken'); } throw error;}What you just built
Section titled “What you just built”- A global uniqueness constraint
- A single event that represents the fact
- A DCB write that rejects conflicts without sagas
If you want to go deeper, read the DCB concept doc or the uniqueness guide.