Clash Policy Group Types Explained: url-test, fallback, and load-balance
A breakdown of how url-test, fallback, and load-balance policy groups work, when to use each, and key parameters—plus ready-to-use config snippets.
Where policy groups sit in the config file
Clash's traffic routing depends on the proxy-groups section of the config. It packages the individual nodes listed under proxies into "logical exits," and the rules under rules reference the names of these policy groups—not any specific node. The upside: switching providers or nodes only means editing proxies and proxy-groups; the rules themselves don't need to change at all.
Every policy group must declare a type, which decides how the client picks a node within that group. The four common types are select (manual selection), url-test (automatic latency testing), fallback (failover), and load-balance (load balancing). select is the simplest—purely manual switching—and is outside the scope of this article; the other three carry "automatic decision" logic and are the ones most often misused. Let's break them down one by one.
url-test: latency-driven automatic switching
url-test is the most common of the three automatic types. In short: the client periodically sends an HTTP request to every node in the group (the target address is set by the url field), records the round-trip latency, and always routes traffic to whichever node currently measures the lowest latency.
Key fields explained:
url: the test target address, usually a fast, reachable endpoint outside China—for example, a lightweight connectivity-check endpoint;interval: the testing interval in seconds, commonly around 300 (5 minutes). Too short adds load on the node side; too long means slow response to latency changes;tolerance: the switching margin in milliseconds. The client only actually switches when a new node's latency is lower than the current one's by more than this margin, which prevents constant back-and-forth switching (and connection resets) caused by minor latency jitter;lazy(supported by Clash Meta/mihomo): when enabled, latency tests only fire when a request is actually made, instead of running on a fixed schedule regardless of traffic—useful for long-idle setups with low connection counts.
The use case is clear: your provider offers a set of near-identical relay nodes (say, multiple exits on the same line), and you don't care which one you actually use as long as latency is lowest. The downside is baked into the same logic—url-test only looks at latency, not packet loss or real throughput, so a node with low latency but heavy rate-limiting won't show any red flags during testing.
fallback: ordered failover
fallback works on entirely different logic from url-test. It doesn't compare latency at all—it probes availability strictly in the order nodes are listed under proxies: as long as the first node is reachable (the probe request succeeds), it keeps using that node; only when the currently active node's probe fails does it move down to the next reachable node in line.
fallback inherently carries a "primary/backup" semantic—you need to plan the node order in advance, putting your preferred primary node first and backups afterward. Its key fields largely mirror url-test's (url, interval, tolerance), but tolerance plays a weaker role here, since the switching decision is based on "reachable or not" rather than "how much faster."
A typical scenario: you have a stable self-hosted node as your primary, plus one or two provider nodes kept as a safety net. Normally you want traffic to prefer the self-hosted node, and only fail over to a backup line if the primary breaks (disconnects, or gets throttled to unusability). This "primary with backup, takeover only when needed" requirement fits fallback better than url-test—url-test would switch away just because a backup measured a slightly lower latency on some given round, while fallback won't; as long as the primary stays reachable, it stays put.
load-balance: spreading connections across nodes
load-balance solves a different problem: when several nodes in a group have similar performance and are all available, you want concurrent connections spread across them rather than piled onto a single node. Its core field is strategy, with two common values:
consistent-hashing: uses consistent hashing based on the request's target address, so the same target domain/IP is very likely to always land on the same node. This reduces connection drops caused by node switching, which is friendlier for scenarios that need session consistency (video playback, large file downloads);round-robin: assigns new connections to nodes in rotating order. Distribution is more even, but two consecutive requests to the same target address may land on different nodes.
load-balance also supports url and interval for health probing—nodes found unreachable are temporarily removed from the pool and re-added once they recover. It's worth stressing that load-balance distributes connection counts, not real-time bandwidth. If one node in the group has an inherently low bandwidth cap, connections routed to it will still be slow—load balancing won't compensate for a single node's weak performance.
Choosing between the three types
Put side by side, the choice boils down to one question: are you solving for "pick the fastest," "keep a primary with a backup," or "spread out concurrency"?
- Nodes in the group are on similar lines and you purely want the lowest latency → use
url-test; - You have a clear primary and backup node, and want the primary preferred with failover only on failure → use
fallback; - The group has many nodes and you want to spread concurrent connections to avoid overloading any single one → use
load-balance; - You just want to switch manually with no automatic logic → use plain
select.
In practice, these types are often nested: an outer select group lets users toggle between "auto latency test," "fixed line," or "manually pick from all nodes," while the "auto latency test" option is itself a url-test group. This keeps automation available without losing manual fallback flexibility.
Ready-to-use config snippets
Below are minimal working examples for each of the three types. Replace the node names under proxies as needed and paste directly into the proxy-groups section of config.yaml.
proxy-groups:
- name: "Auto Select"
type: url-test
proxies:
- "Node A"
- "Node B"
- "Node C"
url: "https://www.gstatic.com/generate_204"
interval: 300
tolerance: 50
- name: "Primary/Backup"
type: fallback
proxies:
- "Self-Hosted Primary"
- "Provider Backup 1"
- "Provider Backup 2"
url: "https://www.gstatic.com/generate_204"
interval: 180
- name: "Balanced Split"
type: load-balance
proxies:
- "Node A"
- "Node B"
- "Node C"
- "Node D"
url: "https://www.gstatic.com/generate_204"
interval: 300
strategy: consistent-hashing
The Clash Meta (mihomo) core additionally supports max-failed-times (how many consecutive failed probes before a node is marked unreachable, reducing false positives from occasional network jitter) and the lazy parameter. If your client is labeled as supporting the Meta core ruleset, you can add these two fields to fine-tune behavior further—the original Clash core simply ignores them without error, but they won't take effect.
Common pitfalls and troubleshooting tips
The most common mistakes when configuring policy groups:
- Mixing nodes with wildly different latencies into the same
load-balancegroup—load balancing doesn't discriminate by latency, so slow nodes still get connections, making the experience worse thanurl-test; - Listing nodes in the wrong order in a
fallbackgroup, putting the primary node last so the backup line is used by default; - Setting
url-test'stolerancetoo low (say, 0 or 5ms)—since latency naturally fluctuates, too small a margin causes frequent switching and repeatedly interrupted connections; - Using a test
urlthat's directly reachable from within mainland China, which makes every node measure near-identical latency and defeats the purpose of distinguishing good nodes from bad ones.
Once policy group types and parameters are paired up correctly, writing the rules section becomes much smoother—rules only need to care about which policy group to route to; which specific node gets used, and when it switches, is already handled by the group's own decision logic. That's the core value of decoupling rules from nodes in Clash's routing system.