Traffic Cloning to Multiple Elasticsearch Clusters with INFINI Gateway
INFINI Gateway duplicates incoming requests across multiple independent processing flows using the clone routing filter, enabling simultaneous writes to separate Elasticsearch clusters without code modifications.
The INFINI Gateway (infinilabs/gateway) provides a declarative mechanism to replicate traffic to multiple Elasticsearch clusters through its pipeline-based architecture. By combining the clone filter with elasticsearch output filters, operators can implement dual-write patterns, blue-green deployments, or multi-region replication purely through YAML configuration.
Core Components of Traffic Cloning
The Clone Routing Filter
The clone filter, implemented in [proxy/filters/routing/clone.go](https://github.com/infinilabs/gateway/blob/main/proxy/filters/routing/clone.go), receives requests and sequentially invokes each configured downstream flow. At line 60 of the source, the CloneFlowFilter.Filter method calls common.MustGetFlow(v) for each flow name v listed in the configuration, then executes flow.Process(ctx) to dispatch the duplicated request into independent processing pipelines.
The Elasticsearch Output Filter
Each downstream flow typically terminates with an elasticsearch output filter that forwards requests to a specific cluster. Connection parameters and cluster definitions are structured in [proxy/output/elastic/config.go](https://github.com/infinilabs/gateway/blob/main/proxy/output/elastic/config.go), while the actual HTTP transmission logic resides in proxy/output/elastic/elasticsearch.go.
Configuration Steps for Multi-Cluster Setup
Define Target Elasticsearch Clusters
Declare each target cluster in gateway.yml under the global elasticsearch section. Each entry requires a unique identifier, endpoint URL, and connection parameters:
elasticsearch:
es-us-east:
elasticsearch: http://us-east.example.com:9200
balancer: round_robin
max_connection_per_node: 50
timeout: 30s
es-eu-west:
elasticsearch: http://eu-west.example.com:9200
balancer: round_robin
max_connection_per_node: 50
timeout: 30s
Implement the Clone Flow
Create an entry flow that uses the clone filter to distribute traffic to multiple named flows. The flows array specifies which downstream flows receive the duplicated request:
flow:
- name: double_write
filter:
- clone:
flows:
- write_us_east
- write_eu_west
continue: false
Configure Response Handling
The clone filter's continue parameter determines client response behavior. When set to false (default), the gateway finishes the request after all clones complete and returns the last flow's response to the client. Lines 63-65 of clone.go implement this logic: if len(filter.Flows) > 0 && !filter.Continue { ctx.Finished() }. Set continue: true to keep the original flow alive and return its response instead.
Complete Configuration Example
The following gateway.yml clones write operations to two geographically separated clusters:
elasticsearch:
es-us-east:
elasticsearch: http://us-east.example.com:9200
balancer: round_robin
max_connection_per_node: 50
timeout: 30s
es-eu-west:
elasticsearch: http://eu-west.example.com:9200
balancer: round_robin
max_connection_per_node: 50
timeout: 30s
flow:
- name: double_write
filter:
- clone:
flows:
- write_us_east
- write_eu_west
continue: false
- name: write_us_east
filter:
- elasticsearch:
elasticsearch: es-us-east
- name: write_eu_west
filter:
- elasticsearch:
elasticsearch: es-eu-west
Execution Flow Deep Dive
When a client request hits the double_write flow, the following sequence occurs:
-
Request Reception: The gateway matches the incoming request to the
double_writeflow in [proxy/filters/routing/clone.go](https://github.com/infinilabs/gateway/blob/main/proxy/filters/routing/clone.go). -
Flow Resolution: The clone filter iterates over the
flowsarray and callscommon.MustGetFlow("write_us_east")andcommon.MustGetFlow("write_eu_west")to resolve the downstream pipeline references. -
Sequential Processing: For each resolved flow, the gateway invokes
flow.Process(ctx), which executes the elasticsearch output filter defined in the downstream configuration. -
Cluster Dispatch: Each elasticsearch output filter forwards the request to its configured cluster using the connection pool established by the
ProxyConfigstruct in [proxy/output/elastic/config.go](https://github.com/infinilabs/gateway/blob/main/proxy/output/elastic/config.go). -
Completion Check: After both flows finish, the
continue: falsesetting triggersctx.Finished(), returning the response fromwrite_eu_west(the last flow in the array) to the client.
Summary
- Clone filter location: [
proxy/filters/routing/clone.go](https://github.com/infinilabs/gateway/blob/main/proxy/filters/routing/clone.go) implements the core duplication logic throughCloneFlowFilter.Filterat line 60. - Zero-code implementation: Traffic cloning requires only YAML configuration changes in
gateway.yml, with no modifications to the gateway source code. - Sequential execution: Flows listed in the clone filter's
flowsarray execute sequentially, not in parallel. - Response control: The
continueparameter determines whether the client receives the last clone flow's response (false) or the original flow continues processing (true). - Configuration reference: Elasticsearch cluster definitions use the schema in [
proxy/output/elastic/config.go](https://github.com/infinilabs/gateway/blob/main/proxy/output/elastic/config.go).
Frequently Asked Questions
What happens if one Elasticsearch cluster fails during cloning?
If a downstream flow fails (e.g., network timeout to es-eu-west), the clone filter continues processing the remaining flows in the sequence. The gateway does not automatically rollback writes to clusters that succeeded earlier in the chain. For critical dual-write scenarios, implement health checks and circuit breakers in the elasticsearch output filter configuration to prevent partial write states.
Can I clone traffic to more than two clusters?
Yes. The flows array in the clone filter accepts any number of flow names. Add additional entries to the array (e.g., write_apac, write_backup) and define corresponding downstream flows with elasticsearch output filters pointing to additional clusters defined in the elasticsearch section of gateway.yml.
How does the continue parameter affect client responses?
When continue: false (default), the gateway marks the request as finished after all clones complete and returns the response from the last flow in the flows array. When continue: true, the original flow resumes after dispatching clones, allowing subsequent filters to process the original response and return it to the client instead.
Where is the clone filter documented?
User-facing documentation for the clone filter parameters and additional examples are available in the repository at [docs/content.en/docs/references/filters/clone.md](https://github.com/infinilabs/gateway/blob/main/docs/content.en/docs/references/filters/clone.md). This documentation covers advanced options including conditional cloning and header manipulation during duplication.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →