Cloudflare workerd - generating configs ahead of time

Cloudflare workerd - generating configs ahead of time

If you're not familiar with Cloudflare Workers already, it's a serverless platform that leverages the V8 runtime & isolate model to provide super fast execution at a nanoservice level. In September 2022, the runtime was made publicly available as workerd. The launch blog provides some background & context, and I highly recommend giving it a read.

The Cloudflare Workers command-line utility, Wrangler, takes a TOML configuration file & transform that into the JSON metadata that the Workers' API is expecting. With workerd, you write the configuration file in Cap'n Proto text format.

Update: for an example of generating configs programmatically with a Cap'n Proto SDK, take a look at https://github.com/KianNH/capnproto-rust-workerd-configs

Cap'n Proto configuration file

using Workerd = import "/workerd/workerd.capnp";

const config :Workerd.Config = (
  services = [
    (name = "main", worker = .mainWorker),
  ],

  sockets = [
    # Serve HTTP on port 8080.
    ( name = "http",
      address = "*:8080",
      http = (),
      service = "main"
    ),
  ]
);

const mainWorker :Workerd.Worker = (
  serviceWorkerScript = embed "hello.js",
  compatibilityDate = "2022-09-16",
);

For the full list of available options, I'll refer you to the Cap'n Proto schema for now as it's not relevant to this post.

As you can see in the mainWorker block, the Worker script is embedded - this means that when you run workerd serve config.capnp, it'll be looking for hello.js on disk as well. That might work for your use-case, but for larger deployments you'll want to distribute just a configuration file.

There's a few options available to us:

  1. Use workerd compile to generate a binary configuration file with the script already embedded, or embed it into a new workerd binary entirely!
  2. Use Cap'n Proto in a language of your choice, such as C++ or Rust, to generate the configuration file.

We'll cover using workerd compile and revisit serialisation from another program in the future.

Using workerd compile

The easiest way to get started with workerd is by using the binary distributed on npm - so we'll assume you have a recent version of Node installed.

If we run npx workerd compile --help, there's one option that is particularly relevant.

--config-only
  Only write the encoded binary config to stdout. Do not attach it to an
  executable. The encoded config can be used as input to the "serve"
  command, without the need for any other files to be present.

--config-only will, rather than creating a new workerd executable with the configuration file embedded, just give us the binary configuration file sent to stdout.

We'll use one of workerd's samples to test it, helloworld.

$ npx workerd compile --config-only ./samples/helloworld/config.capnp > ./config.bin
$ npx workerd serve --binary ./config.bin

If we visit localhost:8080, since the config specifies to listen on all addresses at port 8080, we'll see "Hello World"!

You now have a configuration file that we can distribute alongside workerd without having to also ship the Worker script with it.