Request rewriting and routing: how to choose
The gateway has three ways to rewrite/route requests: request_payload declarative rules, switch-route structural routing, and JavaScript scripts. Performance goes from high to low, expressiveness from low to high. This page is the single authority for choosing among the three.
Boundaries of the three approaches
| Approach | Modifies body? | Performance | Expressiveness | Memory |
|---|---|---|---|---|
request_payload rules | Yes (after translation) | Best (declarative, no script-engine serialization) | Field-level add/delete/modify, inject | Not read into memory |
switch-route rules | No (only decide + redirect) | Good (only structural/small-value checks) | Field existence, small-value equality | Not read into memory |
| Scripts (before/after slots) | Yes | Average (serialization overhead) | Arbitrary logic, cross-field computation | after slot reads into memory |
Decision table
| Scenario | Recommended approach |
|---|---|
Simple field add/delete/modify (temperature, max_tokens, response_format) | request_payload rules |
| Switch model by structural check (has image → stronger model; has web access → web model) | switch-route rules |
| Inject system prompt / append messages (only when absent) | request_payload inject-system-prompt / append-if-missing |
| Cross-field computation / conditional branching / complex checks | Scripts (before slot reads the client's original format) |
| Response content redaction / inject metadata | Response scripts (response_transform) |
In one sentence: request_payload covers about 90% of simple scenarios, switch-route handles pure routing decisions, and scripts handle the remaining complex logic.
Prefer rules for same-protocol routing decisions
As long as the target uses the same protocol as the current route, pure routing decisions ("detect image/web access → switch model") should prefer switch-route rules, not scripts. See the anti-pattern section in Script performance and memory — after-slot scripts read the entire body (including inline base64) into script-engine memory, and large multimodal conversations can easily OOM; switch-route predicates only do structural/small-value checks and never read binary content bytes, so disk spooling stays enabled for large request bodies.
When scripts are required
- The switch is cross-protocol and the check exceeds what structural checks can express (
switch-routesupports cross-protocol, but predicates only do existence/small-value equality). - You need to read/modify body content (not just routing decisions), e.g. conditional rewriting by message content, or injecting different parameters grouped by access key.
- You need response rewriting (
switch-route/request_payloadonly act on requests).
For cross-protocol scenarios, put the script in the before slot to read the client's original format; see Script-based protocol translation.
Attach to upstream or model
- Upstream-level rules/scripts: shared by all models going through this upstream. Good for protocol adaptation and common field injection.
- Model-level rules/scripts: this model only. Model-level overrides upstream-level.
See Upstream and model fields.
FAQ
Q: Is switch-route the same as request_payload's switch-route? Yes. switch-route is a mode of the request_payload rule, but it does not modify the body and evaluates by the client shape before protocol translation. See the mode overview in Upstream and model fields.
Q: After the before slot triggers useModel switching, does the original route's after slot still run? No. Once the before slot triggers an immediate useModel route switch, the entire pipeline is replaced with the target route's, and the original route's after slot does not execute. So the request_payload rules on both the original and target routes must each be configured.
Next: Script performance and memory for performance and anti-patterns; Write your first script transform for a script primer; Upstream and model fields for fields.
