svelte-effect-runtime

Query.batch

Batch many related remote reads into one server call.

Use Query.batch when many parts of a page ask for the same kind of data at the same time. It is for small repeated lookups, not one large report.

When to use this

Use Query.batch for list rows, permission checks, avatars, counters, or related records where each component knows only its own input. SvelteKit collects calls made in the same macrotask and sends them to one server handler.

Minimal working example

import { Query } from "svelte-effect-runtime/server";
import { Effect, Schema } from "effect";

type Author = {
  readonly id: string;
  readonly name: string;
};

const authors = new Map<string, Author>([
  ["ada", { id: "ada", name: "Ada Lovelace" }],
  ["grace", { id: "grace", name: "Grace Hopper" }],
]);

export const get_author = Query.batch(Schema.String, (author_ids) =>
  Effect.succeed((author_id) => authors.get(author_id) ?? null),
);
<script lang="ts" effect>
  import { get_author } from "./authors.remote";

  const author = get_author("ada");
</script>

{#await yield* author}
  <p>Loading author...</p>
{:then value}
  <p>{value?.name}</p>
{/await}

How it works

The client still calls get_author("ada") like a normal query. During a render pass, SvelteKit groups nearby calls and invokes the server handler once with the validated inputs:

export const get_author = Query.batch(Schema.String, (author_ids) =>
  Effect.gen(function* () {
    const rows = yield* Authors.find_many(author_ids);

    return (author_id, index) => rows.get(author_id) ?? null;
  }),
);

The handler returns a resolver function. SvelteKit calls that resolver for each original input, so each component still receives its own result. The returned query remains Effect-yieldable and keeps refresh, set, and withOverride.

Common mistakes

  • Using Query.batch for one expensive request. Use Query for that.
  • Doing one database query per input inside the batch handler.
  • Returning results by array position when input identity is safer.
  • Using batch for live updates. Use Query.live when the server should keep streaming.

On this page