Yet Another Local Tunnel

When working with in local development, we automatically open a free ngrok tunnel to your local app server so the server can send requests to your local app server. Unfortunately free ngrok tunnels are restricted to 120 requests per minute, and if exceeded will return a 429 error.

Starting in[email protected], we have dropped ngrok in favor of a custom tunneling solution which we're calling "" (Yet Another Local Tunnel). is a tunneling solution built on top of Cloudflare Workers and Durable Objects that is designed to be used with the Cloud service, and drops all limits on the number of requests that can be sent to your local app server.

How to use it

If you are on the latest version of the CLI, you can run dev as you normally would, and the CLI will automatically use instead of ngrok. Currently is only available to users of the Cloud service, so if you are self-hosting the server, the CLI will automatically fallback to using ngrok.

You can also continue to use your own custom tunnel URL by passing the -t flag to the CLI, for example dev -t

How it works

When you run the dev command on your local machine, the CLI makes a request to the cloud service to create a new tunnel, returning the tunnel URL (which looks like <tunnelId> That tunnel URL resolves to a Cloudflare Worker that we've deployed (and you can view the source code for it here).

The CLI will then open a new WebSocket connection (powered by partysocket 🎈) which is forwarded to a Durable Object. Finally, the CLI will then register that tunnel URL with your endpoint.

So now that the tunnel setup is complete, when the server wants to send a request to your endpoint, it will make a POST request to the <tunnelId> URL, which again will be handled by that same Cloudflare Worker, which forwards it to tunnel's Durable Object instance, which has in memory the WebSocket connection to your local CLI. The CLI will then receive the request and forward it to your local app server, and respond back to the WebSocket connection with the response from your app server.