Skip to content
sproutboatDocs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Service bindings

Call another of your projects on the same server over loopback.

Configuration

"services": [{ "binding": "PEER", "service": "quote-service" }]

Usage

export default {
  async fetch(request, env, ctx) {
    const response = await env.PEER.fetch(new Request("https://peer/random"));
    return response;
  },
} satisfies ExportedHandler<Env>;

service is the target project’s name. The call goes to the server’s edge over loopback with the target’s hostname, so it uses the same routing, process pool and logs as a public request. It does not leave the server, so the outbound allowlist does not apply. From compatibility date 2026-10-22, fetch() on a binding returns a Promise, as on Workers; await it at every date.

Calling a method over RPC

From compatibility date 2026-11-18, a project written as a WorkerEntrypoint can be called by method, as on Workers. The callee exports the class:

import { WorkerEntrypoint } from "cloudflare:workers";

export default class QuoteService extends WorkerEntrypoint<Env> {
  async fetch(request: Request): Promise<Response> {
    return new Response("quote-service");
  }

  // Callable from a service binding as `await env.PEER.random()`.
  async random(): Promise<{ content: string; author: string }> {
    return { content: "Simplicity is prerequisite for reliability.", author: "Edsger Dijkstra" };
  }
}

The caller awaits the method:

interface Quotes {
  random(): Promise<{ content: string; author: string }>;
}

export default {
  async fetch(request, env, ctx) {
    const quote = await (env.PEER as FetcherAsync<Quotes>).random();
    return Response.json(quote);
  },
} satisfies ExportedHandler<Env>;

sproutboat types types a service binding as FetcherAsync, which has fetch. It cannot read another project’s classes, so name the methods you call with the type argument, as above. See Generated types.

Constraints

Was this page helpful?