// the root "/" route
export default async function(event, next) {
if (next.stepname) return next();
const q = event.url.q;
const liveResult = await client.query(q, {
live: true,
signal: event.signal
});
// Send the initial rows and keep the request open
event.respondWith(liveResult.rows, { done: false });
}
Here, the handler starts a live query and returns the live result rows issued by LinkedQL as "live" response. * The client immediately receives the initial query result
* The HTTP connection stays open
* Mutations to the sent object are synced automatically over the wire and the client-side copy continues to behave as a live object
* If the client disconnects, event.signal is aborted and the live query shuts down
On the client side, you'd do: const response = await fetch('db-service/users?q=...');
const liveResponse = await LiveResponse.from(response);
// A normal JS array — but a live one
console.log(liveResponse.body);
Observer.observe(liveResponse.body, mutations => {
console.log(mutations);
});
// Closing the connection tears down the live query upstream
liveResponse.background.close();
There’s no separate realtime API to plumb manually, no explicit WebSocket setup, and no subscription lifecycle to manage. The lifetime of the live query is simply the lifetime of the request connection. * WAL consumption stays bounded
* live queries are deduped centrally
* API services remain stateless
* lifecycle is automatic, not manually managed
I haven’t personally run this exact topology at scale yet, but it fits the model cleanly and is very much the direction the architecture is designed to support. That engine uses a single replication slot. You specify the slot name like:
new PGClient({ ..., walSlotName: 'custom_slot_name' }); // default is: "linkedql_default_slot" – as per https://linked-ql.netlify.app/docs/setup#postgresql
A second LinkedQL instance would require another slot name:
new PGClient({ ..., walSlotName: 'custom_slot_name_2' });
We’re working toward multi-instance coordination (multiple engines sharing the same replication stream + load balancing live queries). That’s planned, but not started yet.
And of course achieving that "exceptionally high throughput and performance" is the ultimate goal for a system of this nature.
Now, yes — LinkedQL reasons explicitly in terms of transactions, end-to-end, as covered in the paper.
The key structural distinction is that LinkedQL does not have the concept of its own transactions, "since it doesn’t initiate writes". Instead, it acts as an event-processing pipeline that sits downstream of your database — with a strict "transaction-through rule" enforced across the pipeline.
What that transactional guarantee means in practice is this:
Incoming database transactions (via WAL/binlog) are treated as "atomic" units. All events produced by a single database transaction are received, processed, and propagated through the pipeline with their transactional grouping preserved, all the way to the output stream.
Another way to think about it:
You perform high-throughput writes (multi-statement transactions, bulk writes, stored procedures, batching, etc.)
Effectively, a systems that thinks in terms of batching and other throughput-oriented write patterns. LinkedQL just doesn’t initiate its own transactions — it preserves yours, end-to-end.