Skip to content
Merged
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion usage/use-case-examples/high-performance-diffs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# Overview

While [basic/incremental watch queries](/usage/use-case-examples/watch-queries) enable reactive UIs by automatically re‑running queries when underlying data changes and returning updated results, they don't specify which individual rows were modified. To get these details, you can use [**differential watch queries**](/usage/use-case-examples/watch-queries#differential-watch-queries), which return a structured diff between successive query results. However, on large result sets they can be slow because they re‑run the query and compare full results (e.g., scanning ~1,000 rows to detect 1 new item). That’s why we introduced **trigger‑based table diffs**: a more performant approach that uses SQLite triggers to record changes on a table as they happen. This means that the overhead associated with tracking these changes overhead is more proportional to the number of rows inserted, updated, or deleted.

Check warning on line 9 in usage/use-case-examples/high-performance-diffs.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

usage/use-case-examples/high-performance-diffs.mdx#L9

Did you really mean 'UIs'?

Check warning on line 9 in usage/use-case-examples/high-performance-diffs.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

usage/use-case-examples/high-performance-diffs.mdx#L9

Did you really mean 'performant'?

<Note>
**JavaScript Only**: Trigger-based table diffs are available in the JavaScript SDKs starting from:
Expand Down Expand Up @@ -70,7 +70,7 @@
when: { INSERT: sanitizeSQL`json_extract(NEW.data, '$.list_id') = ${firstList.id}` },
onChange: async (context) => {
// // Fetches the todo records that were inserted during this diff
const newTodos = await context.getAll(/* sql */ `
const newTodos = await context.withDiff(/* sql */ `
SELECT todos.*
FROM DIFF
JOIN todos ON DIFF.id = todos.id
Expand Down Expand Up @@ -110,12 +110,12 @@
```

<Warning>
The strings in `when` are embedded directly into the SQLite trigger creation SQL. Sanitize any user‑derived values. The `sanitizeSQL` helper performs some basic sanitization; additional sanitization is recommended.

Check warning on line 113 in usage/use-case-examples/high-performance-diffs.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

usage/use-case-examples/high-performance-diffs.mdx#L113

Did you really mean 'sanitization'?

Check warning on line 113 in usage/use-case-examples/high-performance-diffs.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

usage/use-case-examples/high-performance-diffs.mdx#L113

Did you really mean 'sanitization'?
</Warning>

## Lower-level: createDiffTrigger (advanced)

Set up temporary triggers that write change operations into a temporary table you control. Prefer `trackTableDiff` unless you need to manage lifecycle and locking manually (e.g., buffer diffs to process them later). Note that since the table is created as a temporary table on the SQLite write connection, it can only be accessed within operations performed inside a writeLock.

Check warning on line 118 in usage/use-case-examples/high-performance-diffs.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

usage/use-case-examples/high-performance-diffs.mdx#L118

Did you really mean 'writeLock'?

```javascript
// Define the temporary table to store the diff
Expand Down