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:

  1. Request Reception: The gateway matches the incoming request to the double_write flow in [proxy/filters/routing/clone.go](https://github.com/infinilabs/gateway/blob/main/proxy/filters/routing/clone.go).

  2. Flow Resolution: The clone filter iterates over the flows array and calls common.MustGetFlow("write_us_east") and common.MustGetFlow("write_eu_west") to resolve the downstream pipeline references.

  3. Sequential Processing: For each resolved flow, the gateway invokes flow.Process(ctx), which executes the elasticsearch output filter defined in the downstream configuration.

  4. Cluster Dispatch: Each elasticsearch output filter forwards the request to its configured cluster using the connection pool established by the ProxyConfig struct in [proxy/output/elastic/config.go](https://github.com/infinilabs/gateway/blob/main/proxy/output/elastic/config.go).

  5. Completion Check: After both flows finish, the continue: false setting triggers ctx.Finished(), returning the response from write_eu_west (the last flow in the array) to the client.

Summary

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →