Skip to main content

Understanding Updates in Append-Only Storage

OnDB uses append-only storage. Updates do NOT modify existing data. Instead, a NEW record with the same ID and a newer timestamp is appended. Queries automatically return the latest version of each record. Use queryBuilder().executeUnique() to get the latest version of a single record.

Update Pattern

Update an existing document by finding it, modifying fields, and storing a new version.
TypeScript
// Find the current version
const user = await client.queryBuilder()
  .collection('users')
  .whereField('email').equals('alice@example.com')
  .executeUnique();

if (user) {
  // Store updated version
  await client.store(
    { collection: 'users', data: [{ ...user, name: 'Alice Smith', active: false }] },
    async (quote) => {
      const txHash = await processPayment(quote);
      return { txHash, network: quote.network, sender: walletAddress, chainType: quote.chainType, paymentMethod: 'native' };
    },
    true
  );
  console.log('Updated user');
} else {
  console.log('User not found');
}

How Updates Work

Original Record (Block 100):
{ id: "user_1", name: "Alice", email: "alice@example.com", updatedAt: "2024-01-01" }

After Update (Block 101):
{ id: "user_1", name: "Alice Smith", email: "alice@example.com", updatedAt: "2024-01-02" }

Both records are preserved, but queries return the latest version

Examples

Update Single Field

TypeScript
const user = await client.queryBuilder()
  .collection('users')
  .whereField('id').equals('user_123')
  .executeUnique();

if (user) {
  await client.store(
    { collection: 'users', data: [{ ...user, lastLoginAt: new Date().toISOString() }] },
    paymentCallback,
    true
  );
}

Conditional Update Pattern

TypeScript
const user = await client.queryBuilder()
  .collection('users')
  .whereField('id').equals('user_123')
  .executeUnique();

if (user && user.active) {
  await client.store(
    { collection: 'users', data: [{ ...user, lastActiveAt: new Date().toISOString() }] },
    paymentCallback,
    true
  );
}

Historical Data

Since updates append new records, you can query historical versions:
TypeScript
const allVersions = await client.queryBuilder()
  .collection('users')
  .whereField('id').equals('user_123')
  .includeHistory()
  .execute();

// Sort by updatedAt to see history
const history = allVersions.records.sort(
  (a, b) => new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime()
);

Next Steps

Delete

Soft delete documents

Create

Create new documents