Cloudflare Docs
Workers
Visit Workers on GitHub
Set theme to dark (⇧+D)

About Service bindings

Service bindings are an API that facilitate Worker-to-Worker communication via explicit bindings defined in your configuration.

A Service binding allows you to send HTTP requests to another Worker without those requests going over the Internet. The request immediately invokes the downstream Worker, reducing latency as compared to a request to a third-party service. You can invoke other Workers directly from your code. This makes it possible to communicate with shared services managed by other teams with differing test and release processes. Those services do not need to be hooked up to publicly accessible endpoints. Service bindings facilitate private services to communicate with one another.

Service bindings allow you to:

  • Segment multiple use cases into separate Workers Services that can be explicitly invoked from your code.
  • Achieve better composability on the Workers platform using service-oriented architecture.
  • Create private microservices, to be conditionally invoked from other global network-facing services.

While the interface among Service bindings is HTTP, the networking is not. Unlike the typical microservice architecture, where services communicate over a network and can suffer from latency or interruption, Service bindings are a zero-cost abstraction. When one Worker invokes another, there is no network delay and the request is executed immediately.

For more information, refer to the Runtime API documentation for Service bindings.

Service bindings are a zero-cost abstraction

​​ Set a Service binding

​​ Dashboard

To manage a Workers Service binding:

  1. Log in to the Cloudflare dashboard > Account Home > Workers.
  2. Select your Worker.
  3. Go to Settings > Variables > Service bindings > Edit variables.

​​ Wrangler

To configure a Service binding in your wrangler.toml, use the following syntax:

services = [
{ binding = "<BINDING_NAME>", service = "<WORKER_NAME>", environment = "<ENVIRONMENT_NAME>" }
]

The wrangler.toml options are:

​​ wrangler.toml example

For the example outlined above, a wrangler.toml might look like this:

services = [
{ binding = "auth", service = "authentication" },
{ binding = "logout", service = "logout" }
]

In the example above, the Service bindings for the authentication and logout Workers are accessible in code via env.auth and env.logout, respectively (when using Module syntax), or globally at auth and logout (when using Service Worker syntax).

​​ Local development

Local development is supported for Service bindings. For each Worker, open a terminal and use wrangler dev --local in the relevant directory or use the SCRIPT option to specify the relevant Worker’s entrypoint.

​​ Use Service bindings

Service bindings are available in your Worker code under the <BINDING_NAME> specified in wrangler.toml, via API, or the dashboard. For example, a Service binding that is named “auth” will be available under the binding name auth in your Worker. The API fetch() is implemented on each Service binding by default.

​​ Connected Workers

Workers bound to your Worker will be listed in Workers > your Worker > Triggers > Bound Services. Your team can easily view cross-service dependencies in this manner.

Your team can view cross-service dependencies in the Cloudflare dashboard Account Home &gt; Workers &gt; Triggers

​​ Compose an example Worker

In the following example, you will create a gateway Worker that invokes an auth Worker to handle authorization checks.

​​ Gateway Worker and Service bindings usage

First, you will create both a gateway and auth Worker. Once they are set up, go to the gateway Worker. In order to bind and call the authentication Worker, the gateway Worker needs to set up a Service binding.

To manage Service bindings, go to Account Home > Workers > your Worker > Settings> Variables > Service bindings > Edit variables.

Selecting Edit variables to create new bindings and edit existing bindings that enable Worker-to-Worker communication

Once added, the gateway Worker can access the Workers Service binding directly from the code, as in the example below. It utilizes the fetch API.

export default {
async fetch(request, env) {
// Fetch AUTH service and pass request
const authResponse = await env.auth.fetch(request.clone());
// Return response from the AUTH service if the response status is not 200
// It would return 403 'x-custom-token does not match, request not allowed' response in such case
if (authResponse.status !== 200) {
return authResponse;
}
// Request allowed
// You can write application logic here
// In this case we delegate the logic to an `application` Worker
return await env.application.fetch(request)
},
};

In this setup, only the gateway Worker is exposed to the Internet and privately communicating with the auth and application Workers using Service bindings. In the next section, you will build the auth Worker.

​​ Authentication Workers Service

The following authentication Workers Service code responds with a status code 200 in the case that x-custom-token in the incoming request matches a SECRET_TOKEN secret binding. Note that you implement fetch here, since a Service binding will invoke FetchEvent on the target Worker.

export default {
async fetch(request, env) {
// Read x-custom-token header and make sure it matches SECRET_TOKEN
if (request.headers.get('x-custom-token') === env.SECRET_TOKEN) {
return new Response('Request allowed', { status: 200 });
} else {
return new Response('x-custom-token does not match, request not allowed', { status: 403 });
}
},
};

This auth Workers Service does not need to have a *.workers.dev or other public endpoint. The auth Workers Service is accessed through a Service binding from the gateway Worker directly. The authentication Worker is, effectively, a private Worker Service.