Canary Deployment
Goma Gateway supports canary deployments, allowing you to gradually roll out new versions of your services while reducing risk. With this feature, you can send a controlled portion of traffic to a new backend (e.g., beta or staging), while the majority of requests continue to use the stable version.
This strategy is useful for:
- Testing new versions in production with a limited audience.
- Reducing the impact on potential bugs or regressions.
- Incrementally shifting traffic as confidence grows.
Configuration Fields
-
weight(int, required) Relative weight used when the backend competes for traffic with others in the same pool. Goma uses weighted-random selection — a backend’s probability isweight / sum(weights in the pool). -
exclusive(boolean, optional, default:false) Controls how a matching canary participates in routing:true— If the request matches, this backend receives 100% of the matching traffic (no split with stable backends). Use this for hard-pinned audiences such as internal staff or opted-in beta users.false— If the request matches, this backend joins the stable backends in a weighted pool and competes for the request via itsweight. Use this to send a fraction of a targeted audience to the canary while the rest continues to stable. Non-matching requests never see this backend.
-
priority(int, optional, default:0) Resolves overlaps between exclusive canaries when more than one matches the same request. The highestprioritywins; ties fall back to configuration order (the first matching backend in the list). Ignored for non-exclusive canaries, which always pool together. -
match([]object, optional) A list of conditions used to determine whether traffic should be routed to this backend. Each condition supports the following fields:-
source(string, required) — Where to extract the value from. Valid options:header,query,cookie,ip. -
name(string, required) — The key to match (header name, query parameter, cookie name, or client IP). -
operator(string, required) — How the extracted value should be compared. See Operator Types. -
value(string, required) — The value or values to match against. For operators likein, provide a comma-separated list.
-
Source Types
header— Match based on HTTP request headers.query— Match based on URL query parameters.cookie— Match based on cookies.ip— Match based on the client’s IP address.
Operator Types
equals— Value must exactly match the specified value.not_equals— Value must not equal the specified value.contains— Value must contain the given substring.not_contains— Value must not contain the given substring.starts_with— Value must start with the given substring.ends_with— Value must end with the given substring.regex— Value must match the given regular expression.in— Value must be one of the specified values (comma-separated).
Example: Canary Deployment Configuration
routes:
- path: /
name: canary
enabled: true
hosts:
- api.example.com
backends:
- endpoint: "https://api-stable-example"
weight: 80
- endpoint: "https://api-beta-example"
weight: 20
exclusive: true
match:
- source: "header"
name: "X-Canary-User"
operator: "equals"
value: "true"
- source: "query"
name: "version"
operator: "equals"
value: "beta"
- source: "cookie"
name: "beta_user"
operator: "in"
value: "admin,tester,developer"
In this configuration the beta backend is exclusive, so any request that satisfies one of the match rules is routed to the beta backend in full; all other traffic goes to the stable backend.
Example: Non-Exclusive Canary (Partial Split)
Use a non-exclusive canary when you want a fraction of a targeted audience to hit the canary while the rest continues to stable. The canary joins the stable backends in a weighted pool for matching requests.
routes:
- path: /
name: canary
enabled: true
hosts:
- api.example.com
backends:
- endpoint: "https://api-stable-example"
weight: 90
- endpoint: "https://api-beta-example"
weight: 10
exclusive: false
match:
- source: "header"
name: "X-Beta-Audience"
operator: "equals"
value: "true"
For requests without X-Beta-Audience: true, the canary is excluded — 100% of traffic goes to stable. For requests with the header, the pool is {stable(90), beta(10)}, so roughly 10% of those users are routed to the canary and the remaining 90% still hit stable. This gives you a gradual ramp within a targeted segment.
Example: Overlapping Exclusive Canaries with Priority
When several exclusive canaries could match the same request, use priority to decide which one wins deterministically.
backends:
- endpoint: "https://api-stable-example"
weight: 100
- endpoint: "https://api-beta-example"
weight: 20
exclusive: true
priority: 1
match:
- source: "header"
name: "X-Beta-Audience"
operator: "equals"
value: "true"
- endpoint: "https://api-staff-example"
weight: 20
exclusive: true
priority: 10
match:
- source: "cookie"
name: "group"
operator: "equals"
value: "staff"
A staff member who also has X-Beta-Audience: true matches both canaries; the staff backend wins because its priority is higher. Equal priorities fall back to the order the backends appear in the configuration.