Skip to main content

Documentation Index

Fetch the complete documentation index at: https://paper.brimble.io/llms.txt

Use this file to discover all available pages before exploring further.

What happens between a user typing your URL and your service returning a response. This page covers the request path end-to-end so you can debug latency, errors, and unexpected behavior with the right mental model. Brimble runs every public request through Cloudflare before it reaches Brimble’s own infrastructure. Cloudflare provides DDoS protection, edge caching, and the secure tunnel into Brimble’s network. From your service’s perspective, the request comes from Brimble’s gateway, but the first hop, every time, is Cloudflare.

High-level flow

User
 │  1. DNS resolves your-domain.com → Cloudflare edge

Cloudflare (global edge)
 │  2. TLS handshake
 │  3. WAF + DDoS filtering, optional caching
 │  4. Tunnel into Brimble


Brimble Gateway (the proxy)
 │  5. Match the hostname to a Brimble domain
 │  6. Apply ingress rules (redirect? maintenance? auth?)
 │  7. Resolve which container instance to send to
 │  8. Forward


Your service
 │  9. Code runs, returns response


Gateway → Cloudflare → User
The next sections cover what each step actually does.

1. DNS

Your domain’s DNS resolves to Cloudflare’s edge. For default URLs (<project>.brimble.app), Brimble already has the wildcard pointed at Cloudflare. For a custom domain, your CNAME pointing at gateway.brimble.app (or an A record at the apex) ultimately resolves to Cloudflare’s anycast IPs. Until DNS propagates, no other layer matters. If dig your-domain.com +short doesn’t resolve to Cloudflare’s edge, the request never enters Brimble’s flow.

2. Cloudflare TLS

Cloudflare terminates TLS at the user-facing edge using a Let’s Encrypt certificate Brimble provisions for the hostname. For Brimble-managed domains the cert is issued automatically; for custom domains the cert is issued the first time the domain points at the edge and renewed before expiry. After TLS, the request is plaintext HTTP between Cloudflare and Brimble’s gateway, but it’s tunneled, see step 4.

3. WAF, DDoS, and caching

Before forwarding, Cloudflare:
  • Filters DDoS and abusive traffic at the network and application layers. A request that triggers Cloudflare’s filters never reaches Brimble.
  • Optionally serves from cache for cacheable responses. By default, Brimble configures the cache to leave HTML uncached and respect cache headers for static assets. When a deployment goes active, Brimble purges the cache for the project’s hostnames so users see the new version immediately.
  • Rate-limits abusive single-source traffic. The limits are independent of your project’s compute size, they’re an infrastructure-level guardrail.
A small set of paths (websocket upgrades, gRPC, anything with auth headers) is always passed through untouched.

4. Cloudflare tunnel into Brimble

Cloudflare reaches Brimble’s gateway through a Zero Trust tunnel. Each Brimble server runs a tunnel agent that registers with Cloudflare; Cloudflare sends the request through the tunnel to the right server. There’s no public IP for Brimble’s gateway, it’s only reachable through Cloudflare. What this means for you:
  • Your service’s origin IP is never directly exposed.
  • DDoS attacks hit Cloudflare’s edge, not Brimble.
  • Brimble can move servers around without DNS changes.

5. Hostname matching

The gateway looks up the request’s hostname against the domain table. Three outcomes:
  • Match found, project attached, proceed.
  • Match found, no project, return 404 “Deployment Not Found”.
  • No match, return a generic “not connected to Brimble” page.
The hostname is an exact match. app.example.com is a different lookup from example.com.

6. Ingress rules

Before the request reaches your container, the gateway runs through several gates in order. Each can short-circuit the request.

Project disabled

If the project is paused or disabled (typically due to billing), the gateway returns 403 Deployment Disabled.

Maintenance mode

If you’ve toggled maintenance on for the project, the gateway returns 200 with a maintenance page.

Password protection

If the project has password protection on, the gateway checks for a session cookie (x-brimble-session). Missing or invalid → 401 with a password prompt page. Successful login sets the cookie; subsequent requests pass through until the cookie expires.

MCP authentication

For MCP server projects with authentication enabled, the gateway checks the x-brimble-key header. Missing or invalid → 401 Unauthorized.

Redirect

If the domain has a redirect URL configured, the gateway returns the configured status code (301, 302, 307, or 308) with the destination in the Location header.

Deployment not yet live

If the project hasn’t finished its first deployment, or the latest deployment is failed and there’s no previous active version, the gateway returns 202 (still deploying) or 409 (failed).

7. Backend resolution

The gateway picks which container instance to send the request to.
  • Single-container projects, the request goes to the project’s container at its internal IP and port.
  • Multi-container projects (with an autoscaling group), the gateway uses Consul service discovery to find healthy instances and picks the container with the fewest active connections (least-connection algorithm). If that container errors at connection time, the gateway falls back to another instance.
The selection happens per request, sticky sessions aren’t the default. If your service depends on session affinity, store session state in a database or shared cache, not in the container’s memory.

Service discovery and DNS failover

How the gateway actually resolves a project name to a live container, and why a single DNS hiccup doesn’t take traffic down:
  • Consul is the source of truth. Every running container is registered with Consul on deploy and continuously health-checked. A container that fails its check is taken out of rotation immediately, the next request from the gateway no longer sees it as a candidate.
  • CoreDNS sits in front of Consul. Brimble runs CoreDNS as a system job on every host in a region. The gateway’s DNS lookups go to the local CoreDNS instance, which is fronted by Consul’s standard service-discovery semantics.
  • Multiple Consul agents, with sequential failover. CoreDNS is configured to forward DNS queries to a list of Consul agents, starting with the local one and stepping through every other Consul agent in the cluster in order. Each forwarder has a health check, if one Consul agent is unreachable or unhealthy, CoreDNS skips it and asks the next. The query only fails if every Consul agent in the cluster is down, which has an extremely small blast radius in practice.
  • Lookups are cached. Successful resolutions are cached at the gateway for a few minutes. A briefly-flapping DNS dependency doesn’t translate into a flapping user-facing experience.
What this means for you:
  • A single Consul or DNS instance failing in the middle of a deploy doesn’t break routing for other projects.
  • A new deployment becomes routable within seconds of registering with Consul; you don’t wait on long DNS TTLs.
  • A removed deployment stops receiving traffic the moment its health check fails or its container is deregistered, even before any cache expires, because the gateway tracks active connections and fails over on connection error.

8. Forward to your container

The gateway opens a connection to your container’s address and forwards the request, including:
  • The original method, path, and query string.
  • The original body (with content-length preserved).
  • All headers, after the strip and inject above.
For uploads (Content-Type: multipart/form-data or large bodies), the gateway streams the body through without buffering. For WebSockets (paths like /ws/*, /socket.io/*, or any request with Upgrade: websocket), the gateway upgrades the connection and proxies bidirectionally. For gRPC (Content-Type: application/grpc*), the gateway forwards using HTTP/2 cleartext (h2c).

9. Your service handles the request

Your code runs and returns a response. The gateway forwards it back, with two transformations:
  • Cache-Control: no-store is set on HTML document responses, and etag / last-modified are stripped, so the next page load gets the freshest deployment.
  • Static assets (JS, CSS, images, fonts) pass through with their cache headers intact, so Cloudflare can cache them on the way back out.

10. Back to the user

The response travels back: gateway → Cloudflare tunnel → Cloudflare’s edge → user’s browser. Cacheable responses sit on Cloudflare’s edge so the next user gets them without round-tripping to Brimble.

The correlation header

Every response Brimble produces includes an x-brimble-id header with a unique ID for the request. Log it from your service if you want a single ID that correlates a user-visible request to the run on Brimble’s side, useful when reporting an issue to support.

Next steps

Last modified on May 10, 2026