Routes
Infra > Routes. The whole routing table, in the order the gateway reads it, and the editor every route is opened in. This is the screen you spend the most time on.

Five routes in the order they are read. Billing, Docs portal and Inventory carry the UI mark, Billing and Orders API require a session (AUTH), Inventory answers by itself in maintenance, and Catch-all on path: /** sits last - a catch-all anywhere else would answer for everything under it.
The list
One row per route: its name, what it decides about access, and one Matching and target column on two lines: what it matches, then where it sends. Order is significant - the first route that matches wins - so the table is ordered, not sorted.
- The drag handle moves a route up or down and saves at once. It only works on the whole list: with a search or a kind filter active the handle goes quiet and says why, because dragging row three above row one of a filtered view would move it above whatever really sits first.
- The heart before the name says whether the route's target is there: green when it is up, broken and red when it is down, with the reason in its tooltip. No heart while nothing is known yet, for a route that answers by itself, or for a disabled one. A second mark appears for a UI route (one that serves pages in a browser).
- The access badges say what Meerkat itself requires:
AUTHsigned in,ORGin an organisation,ORG-2in one of two named ones,DENYnobody, a dash for delegated. A badge counting endpoints appears when the route refines access per operation, and clicking it opens Endpoint security. - Row actions: open the route in the data plane (UI routes only), enable or disable, duplicate, delete.
- The search matches a route's name, its upstream and its path patterns - which is what you usually remember about it. The picker beside it narrows to UI routes or to service routes.
Duplicate makes a copy with a fresh identity, disabled, placed right after the original. That is the intended way to try a variant: another upstream, another organisation's access, compared side by side without retyping.
Is the target up?
The heart answers it for every route that sends to a service.
| Heart | When |
|---|---|
| green | the service is found in the cluster with at least one replica ready, or an external target accepts a connection |
| broken, red | no replica ready, the target refuses or does not resolve, or the circuit breaker is open |
| none | not known yet, a route that answers by itself, or a disabled route |
The gateway checks every 30 seconds, in the background: it reads the replica count Docker or Swarm declares, and opens a bare TCP connection to anything else (a Kubernetes service, an external host). No HTTP request is sent, so the upstream sees no call, no sign-in and no line in its logs. Each node checks from where it stands. When a heart changes, the list follows without a reload.
Three buttons in the banner
- Routing test composes a fictional request and tells you which route takes it. Use it before moving anything: it answers the only question the order is about.
- Global holds what is true of every route at once: the Unavailable switch that closes all of them (sign-in pages keep working, and anyone who administers or develops here still gets through), how long any route waits for a service before answering 504, and the ceiling on what a body-rewriting filter may hold in memory. The button itself turns amber and reads Unavailable while the switch is on, so nobody has to open it to find out.
- OIDC / JWT holds the keys that sign the identity JWT your services verify: at the top the well-known addresses - the internal discovery document to hand a backend (the recommended one), the OpenID provider's public discovery while it answers, and the JWKS - then the Public address, the issuer every token carries, chosen among the application plane's public names (
meerkatwhile none is declared, with a link to declare one), each algorithm's public half, the rotation, and which routes sign with what. Point a service at the discovery document and it needs nothing else: it learns the issuer and the keys from it. The token'skidnames the key, and the key carries its algorithm, so the algorithm is chosen once, in Auth forward; the service takes it from the key, never from the token's header. Both addresses are on the internal plane, port 7070, and only there. See The identity JWT. Under the keys, OIDC clients lists the applications that sign their users in through Meerkat, and the routes bound to each (Enterprise edition): see Meerkat as an OpenID provider.
The editor
Clicking a row opens the route in the right drawer. The drawer is in the URL - /infra/routes/:id/:section - so a section can be bookmarked and a refresh comes back to it.

The editor on Orders API: the section list on the left with its stars and its counts, and the Target panel on the right - mode, upstream, the two waits, the circuit breaker and the API contract.
The name sits in the header. The left column lists the sections, grouped:
| Group | Sections |
|---|---|
| - | Target, Identity, OpenTelemetry |
| Filters | Security, Predicates, Gates, Rate limits |
| Modifiers | Incoming, Outgoing, Auth forward |
| UI | Locales, Color scheme, User button, User info, Custom |
Identity is what the route knows about the caller. Two sections spend it: Auth forward sends it to the service, User info puts it on the page. OpenTelemetry decides whether the route is traced (see traces).
Reading the marks
- A star marks a section that is always required: Target and Predicates. It is a fact about routes, so it never goes away.
- Red marks a section with something missing right now. It goes away when the gap is filled.
- A number in brackets is how many items a section holds (three predicates, two gates).
- The Security section carries the level it poses (
AUTH,ORG,DENY, or a dot when nothing is posed but users are excepted), so an open route and a closed one do not read alike in the list.
What is missing, and Save
Save stays disabled until the route is valid and something has changed. Beside it, a red N to fix button lists every gap: each line names the section and jumps to it. There is no hunting through fifteen sections for the field that is wanted.
Saving keeps the drawer open and applies the route at once. Closing with unsaved changes asks first, and while there are unsaved changes a click outside does not close the drawer.
Sections that go quiet
- The UI sections stay visible but disabled until the UI checkbox on their group is ticked. A route is always a service; UI comes on top.

A UI section once the box is ticked: here Color scheme, which says how the served application takes a light or dark choice.
- Incoming, Identity and Auth forward are disabled when the route answers by itself (redirect, maintenance, respond, files). This is not tidiness: the gateway drops every request filter on such a route, so editing them would write settings it throws away.
The Target section
The mode decides everything else on the panel.
| Mode | What the route does |
|---|---|
| Proxy | Fetches from a service and hands back what it says |
| Redirect | Sends the browser elsewhere |
| Maintenance | Serves the built-in unavailable page |
| Respond | Builds an answer from a template, calling nothing |
| Files | Serves files uploaded on the route - a font, a stylesheet, a script - calling nothing |
On a proxy route you also set:
- Upstream - the scheme is chosen, never typed:
httpfirst because inside a cluster TLS ends at the gateway,httpsfor a third party,h2cfor a gRPC service. Services the gateway discovered are offered in the field. - When the service is slow or down - connect and first-answer timeouts, which inherit the Global values unless set here. Past the connect timeout the caller gets a 502 (the service cannot be reached), past the first-answer one a 504 (it was reached and did not answer in time). What follows the first line is never bounded, so a download or a websocket runs as long as it needs.
- Stop calling this service when it stops answering - the circuit breaker: after N failures in a row, callers get the unavailable page at once, and after the delay the service is met by one request rather than by everything that piled up. A 500 does not count towards it.
- The API contract - no spec, one published by the service (a URL relative to the upstream), or one deposited here as a file. A spec is what unlocks the endpoint screens and the developer swagger.

The bricks stack in a panel, each with its own explanation and its own remove button. Here: two path patterns, four methods, and a header that accepts a short list of values.
Predicates, gates, filters
The sections that hold bricks are the vocabulary of routing, and they have their own reference:
- Predicates - the ways a route decides a request is for it.
- Filters - the ways it transforms one, and the gates that refuse it.

Filters apply in the order they are listed, and the arrows on each card move it up or down.
Common mistakes
- Reordering with a search active. The handle refuses and says so; clear the search first.
- Expecting a new route to be reachable. A duplicate is created disabled, on purpose.
- Two routes matching the same paths. Perfectly legal, and the reason order exists. Use the Routing test rather than reasoning about it.
- Editing Incoming, Identity or Auth forward on a redirect. The sections are disabled; what you want is probably Outgoing, which applies to every mode.
- Looking for endpoint rules with no spec. Declare the OpenAPI spec on the route's Target section first.