<!--
Copyright (c) 2024, 2025, Oracle and/or its affiliates.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.

This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation.  The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.

This program is distributed in the hope that it will be useful,  but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
the GNU General Public License, version 2.0, for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-->

# Routing Guidelines Cookbook

This cookbook provides recipes for creating and managing Routing Guidelines within MySQL InnoDB Cluster, ClusterSet, and ReplicaSet. Each recipe includes step-by-step instructions and sample code for configuring routing rules tailored to specific application requirements.

## Recipe 1: Cluster: Default Routing Guideline

In this setup, we'll create a default Routing Guideline for an InnoDB Cluster.

When no custom guideline is provided, the AdminAPI generates a default configuration based on the topology type. This default reflects MySQL Router's default behavior for that topology.

For InnoDB Cluster, the default guideline routes write operations to the Primary member and read operations to Secondary members, if available, falling back to the Primary when needed. This setup offers a balanced and resilient approach, suitable for many common workloads.

### Step 1: Create the guideline

Start by creating a Routing Guideline using the default settings for the Cluster.

```
// Get the Cluster object
cluster = dba.get_cluster()

// Create a default Routing Guideline
rg = cluster.create_routing_guideline("default")
```

This creates a Routing Guideline named "default" for the Cluster, which can then be reviewed and modified as needed.

### Step 2: Review the guideline configuration

To view the details of the guideline, including destinations and routes, you can examine the JSON document generated by the guideline. This document shows the structure and logic that the Router will use to direct traffic.

```
// Check the JSON document
rg.as_json()
```

Example JSON output:
```
{
    "destinations": [
        {
            "match": "$.server.memberRole = PRIMARY",
            "name": "Primary"
        },
        {
            "match": "$.server.memberRole = SECONDARY",
            "name": "Secondary"
        },
        {
            "match": "$.server.memberRole = READ_REPLICA",
            "name": "ReadReplica"
        }
    ],
    "name": "default",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Primary"
                    ],
                    "priority": 0,
                    "strategy": "round-robin"
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort = $.router.port.rw",
            "name": "rw"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Secondary"
                    ],
                    "priority": 0,
                    "strategy": "round-robin"
                },
                {
                    "classes": [
                        "Primary"
                    ],
                    "priority": 1,
                    "strategy": "round-robin"
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort = $.router.port.ro",
            "name": "ro"
        }
    ],
    "version": "1.1"
}
```

You can inspect the destinations and routes, separately and in a user-friendly manner, to understand how different types of traffic will be directed.

```
// List the destinations
rg.destinations()
```

Example output:
```
+-------------+------------------------------------+
| destination | match                              |
+-------------+------------------------------------+
| Primary     | $.server.memberRole = PRIMARY      |
| Secondary   | $.server.memberRole = SECONDARY    |
| ReadReplica | $.server.memberRole = READ_REPLICA |
+-------------+------------------------------------+
3 rows in set (0.0000 sec)
```

The output shows destinations and their corresponding matching rules, defined using `$.server.*` variables such as `$.server.memberRole`. Servers in the topology are evaluated against these rules, and those that match are associated with the respective destination. This classification helps define groups of servers for routing decisions.

```
// List the routes
rg.routes()
```

Example output:
```
+------+---------+-----------+-----------------------------------------+----------------------------------------------+-------+
| name | enabled | shareable | match                                   | destinations                                 | order |
+------+---------+-----------+-----------------------------------------+----------------------------------------------+-------+
| rw   |       1 |         1 | $.session.targetPort = $.router.port.rw | round-robin(Primary)                         |     0 |
| ro   |       1 |         1 | $.session.targetPort = $.router.port.ro | round-robin(Secondary), round-robin(Primary) |     1 |
+------+---------+-----------+-----------------------------------------+----------------------------------------------+-------+
2 rows in set (0.0000 sec)
```

The `$.session.*` variables represent attributes of each incoming client session to be routed by the Router, while `$.router.*` variables expose the configuration and state of the Router instance managing the session.

Client sessions are routed to a destination server selected from the pool defined in the destinations list of the first matching route.

For example, the `ro` route from the output above, defines the following server pool behavior:

  - Round-robin among available Secondary servers.
  - Fallback to the Primary server if no Secondary servers are available.

### Step 3: Checking the Routing Guideline Server Mapping

The `.show()` function provides a comprehensive overview of how the guideline applies to the topology. It maps each destination to the servers that meet the destination criteria, showing the current routing setup and identifying any unreferenced servers.

```
// Check the guideline information and server mapping
rg.show()
```

Example output:
```
rg.show()
Routing Guideline: 'default'
Cluster: 'devCluster'

Routes
------
  - rw
    + Match: "$.session.targetPort = $.router.port.rw"
    + Destinations:
      * 127.0.0.1:3310 (Primary)

  - ro
    + Match: "$.session.targetPort = $.router.port.ro"
    + Destinations:
      * 127.0.0.1:3320, 127.0.0.1:3330 (Secondary)
      * 127.0.0.1:3310 (Primary)

Destination Classes
-------------------
  - Primary:
    + Match: "$.server.memberRole = PRIMARY"
    + Instances:
      * 127.0.0.1:3310

  - Secondary:
    + Match: "$.server.memberRole = SECONDARY"
    + Instances:
      * 127.0.0.1:3320
      * 127.0.0.1:3330

  - ReadReplica:
    + Match: "$.server.memberRole = READ_REPLICA"
    + Instances:
      * None

Unreferenced servers
--------------------
  - None
```

### Step 4: Activating the Routing Guideline

To put the guideline into effect, set it as the active routing guideline. This makes the default guideline the primary routing configuration for handling traffic.

```
// Activate the routing guideline
cluster.set_routing_option("guideline", "default");
```

**Note**: Once the guideline is activated, it may take some time for all MySQL Router instances to retrieve it from the metadata. The speed of this process depends on the configured metadata-cache refresh interval.

### Step 5: Verify Router Adoption of the new active Guideline

```
// Check Router's information and active guideline
cluster.list_routers();
```

Example output:
```
cluster.list_routers()
{
    "clusterName": "devCluster",
    "routers": {
        "domus::my_router": {
            "currentRoutingGuideline": "default",
            "hostname": "domus",
            "lastCheckIn": "2024-11-28 14:25:41",
            "localCluster": "devCluster",
            "roPort": "6447",
            "roXPort": "6449",
            "rwPort": "6446",
            "rwSplitPort": "6450",
            "rwXPort": "6448",
            "supportedRoutingGuidelinesVersion": "1.1",
            "version": "9.3.0"
        },
        "domus::my_router2": {
            "currentRoutingGuideline": null,
            "hostname": "domus",
            "lastCheckIn": null,
            "localCluster": "devCluster",
            "roPort": "6447",
            "roXPort": "6449",
            "rwPort": "6446",
            "rwSplitPort": "6450",
            "rwXPort": "6448",
            "supportedRoutingGuidelinesVersion": "1.1",
            "version": "9.3.0"
        }
    }
}
```

### Summary

You have now successfully created, reviewed, and activated a default Routing Guideline. This guideline will:

  - Route write operations (rw) to the Primary node.
  - Route read operations (ro) to Secondary nodes, with the Primary as a fallback.

For more complex scenarios, you can modify this guideline or create additional guidelines as needed.

## Recipe 2: ClusterSet: High Availability and Disaster Recovery

For High-Availability setups, routing guidelines need to support failover, ensuring that traffic can be redirected to alternative nodes in case of outages. This recipe configures a Routing Guideline that prioritizes local nodes but includes remote nodes as failover options. It routes read-write traffic to primary nodes and read-only traffic across secondary and scale-out nodes, with multiple fallback levels for maximum availability.

### Step 1: Create the High Availability and Disaster Recovery Guideline

Start by creating a Routing Guideline named HA_DR_Guideline for high availability, in a ClusterSet.

```
// Get the ClusterSet object
clusterset = dba.get_cluster_set()

// Create the routing guideline
rg = clusterset.create_routing_guideline("HA_DR_Guideline")
```

### Step 2: Add Destinations for High Availability and Disaster Recovery

Define each destination based on server roles, availability, and location (local vs. remote) using `.add_destination()`. This classification enables precise control over how traffic is routed and provides clear fallback options.

```
// Add primary and secondary destinations for local and remote clusters
rg.add_destination(
  "Primary_Local",
  "$.server.clusterRole = PRIMARY AND $.server.memberRole = PRIMARY AND $.server.isClusterInvalidated = false AND $.server.clusterName = $.router.localCluster");

rg.add_destination(
  "Primary_Remote",
  "$.server.clusterRole = PRIMARY AND $.server.memberRole = PRIMARY AND $.server.isClusterInvalidated = false AND $.server.clusterName <> $.router.localCluster");

rg.add_destination(
  "Secondary_Local",
  "$.server.memberRole = SECONDARY AND $.server.isClusterInvalidated = false AND $.server.clusterName = $.router.localCluster");

rg.add_destination(
  "Secondary_Remote",
  "$.server.memberRole = SECONDARY AND $.server.isClusterInvalidated = false AND $.server.clusterName <> $.router.localCluster");

rg.add_destination(
  "Scale_Out_Local",
  "$.server.memberRole = READ_REPLICA AND $.server.isClusterInvalidated = false AND $.server.clusterName = $.router.localCluster");

rg.add_destination(
  "Scale_Out_Remote",
  "$.server.memberRole = READ_REPLICA AND $.server.isClusterInvalidated = false AND $.server.clusterName <> $.router.localCluster");

rg.add_destination(
  "Read_Only_Fallback_Local",
  "$.server.isClusterInvalidated = true AND ($.server.memberRole = SECONDARY OR $.server.memberRole = READ_REPLICA) AND $.server.clusterName = $.router.localCluster");

rg.add_destination(
  "Read_Only_Fallback_Remote",
  "$.server.isClusterInvalidated = true AND ($.server.memberRole = SECONDARY OR $.server.memberRole = READ_REPLICA) AND $.server.clusterName <> $.router.localCluster");
```

In this example, _Local and _Remote versions of a destination refer to the location of each specific Router instance.

When bootstrapping MySQL Router, the `--conf-target-cluster` option can be used to specify the name of the InnoDB Cluster that is considered "local" to the Router (e.g., located in the same data center, region, or any other criteria relevant to your setup). Consequently, Local servers are those located in the same data center as the Router, irrespective of whether the Cluster is a PRIMARY or SECONDARY one.

### Step 3: Add Routes for Read-Write and Read-Only Traffic

Define two primary routes for handling different types of traffic:

  - Read-Write (rw_traffic): Prioritizes local primary servers with a remote primary as a fallback.
  - Read-Only (ro_traffic): Balances read-only traffic across local secondary and scale-out nodes, with multiple fallback levels.

Use `.add_route()` to define each route and specify its destination classes and options.

```
// Add route for read-write traffic
rg.add_route(
  "rw_traffic",
  "$.session.targetPort in ($.router.port.rw, $.router.port.rw_split)", ["first-available(Primary_Local, Primary_Remote)"], {"connectionSharingAllowed": True, "enabled": True});

// Add route for read-only traffic
rg.add_route(
  "ro_traffic",
  "$.session.targetPort = $.router.port.ro",
  [
    "round-robin(Secondary_Local, Scale_Out_Local)",
    "round-robin(Secondary_Remote, Scale_Out_Remote)",
    "round-robin(Primary_Local, Primary_Remote)",
    "round-robin(Read_Only_Fallback_Local, Read_Only_Fallback_Remote)"
  ],
  {"connectionSharingAllowed": True, "enabled": True});
```

  - rw_traffic route: Routes read-write traffic to Primary_Local first and falls back to Primary_Remote.

  - ro_traffic route: Routes read-only traffic to local secondary and local scale-out nodes first. If those are unavailable, it falls back to remote secondary and remote scale-out nodes, then to primary nodes, and finally to read-only fallback nodes if needed. The multi-level priority ensures continuous availability.

###  Step 4: Review the Routing Guideline Configuration

Once the destinations and routes are set up, use `.as_json()` to review the full configuration of the guideline, or use `.show()` for a detailed view of destination mappings and matching servers.

```
// Check the JSON document for the routing guideline
rg.as_json();

// Display a detailed overview of the routing guideline
rg.show();
```

### Step 5: Remove unnecessary destinations and/or routes

When the guideline was created in Step 1, a default guideline was created since the `json` option was not used. To remove unnecessary destinations or routes, use `.remove_destination()` and `.remove_route()` accordingly.

```
// Remove a destination
rg.remove_destination("PrimaryClusterReadReplica")

// Remove a route
rg.remove_route("ro")
```

### Step 6: Activate the High Availability and Disaster Recovery Guideline

After configuration, activate the guideline to make it the default routing setup for the cluster.

```
// Check if any guideline is active in the topology
clusterset.router_options()

// Activate the high-availability routing guideline
clusterset.set_routing_option("guideline", "HA_DR_Guideline");
```

### Summary

With the HA_DR_Guideline in place, you have a setup that ensures:

  - Read-Write Traffic is directed first to local primary nodes, with remote primary fallback.
  - Read-Only Traffic is distributed across local secondaries and scale-out nodes, with multiple levels of fallback, including remote and primary nodes.

This configuration provides redundancy and high availability, ensuring seamless failover across both local and remote clusters. You can test this setup by simulating node outages or session redirection to confirm that traffic is appropriately routed to the designated fallback nodes.

## Recipe 3: Geolocation-Based Routing / Compliance

In scenarios where applications need to route traffic based on geographic location or compliance requirements, geolocation-based routing guidelines are essential.
This recipe demonstrates how to create a Routing Guideline from a predefined JSON file, ensuring traffic is directed based on server regions and compliance tags for regulatory adherence and optimal latency.

### Step 1: Create a JSON File for the Routing Guideline

Programmatically, or interactively in MySQL Shell, create the JSON document and assign it to a variable.

This document defines destinations based on server geolocation and compliance, along with routes that match session attributes such as IP address and region.

```
// Create the JSON document to store the guideline
guideline = {
    "destinations": [
        {
            "match": "$.server.address IN ('us-east-1.example.com', 'us-west-2.example.com')",
            "name": "US_Regions"
        },
        {
            "match": "$.server.address IN ('eu-central-1.example.com', 'eu-west-1.example.com')",
            "name": "EU_Regions"
        },
        {
            "match": "$.server.tags.compliance = 'GDPR'",
            "name": "GDPR_Compliant"
        }
    ],
    "name": "Geo_Based_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": True,
            "destinations": [
                {
                    "classes": [
                        "US_Regions",
                        "EU_Regions"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": True,
            "match": "NETWORK($.session.sourceIP, 24) = NETWORK('192.168.1.0', 24) OR NETWORK($.session.sourceIP, 8) = NETWORK('10.0.0.0', 8)",
            "name": "geo_based"
        },
        {
            "connectionSharingAllowed": True,
            "destinations": [
                {
                    "classes": [
                        "GDPR_Compliant"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": True,
            "match": "$.session.connectAttrs.region = 'EU'",
            "name": "compliance_based"
        }
    ],
    "version": "1.1"
}
```

### Step 2: Create the Routing Guideline using the JSON document

Instead of manually adding destinations and routes, use the JSON file directly to create the guideline. This approach streamlines setup and ensures consistency when deploying similar guidelines across environments.

```
// Create the routing guideline from the JSON file
rg = replicaset.create_routing_guideline("Geo_Based_Guideline", guideline);
```

### Step 3: Alter the Guideline as needed

Once the guideline has been created, you can modify destinations or routes using `set_destination_option()` and `set_route_option()` as follows:

```
// Get the guideline object
rg = replicaset.get_routing_guideline("Geo_Based_Guideline");

// Modify the match expression for the 'EU_Regions' destination
rg.set_destination_option("EU_Regions", "match", "$.server.address IN ('eu-west-1.example.com', 'eu-south-1.example.com')");

// Disable the 'compliance_based' route temporarily
rg.set_route_option("compliance_based", "enabled", False);
```

In this example:

  - Destination Modification: The EU_Regions destination is updated to match additional or alternative server addresses, adjusting traffic routing as needed.

  - Route Modification: The compliance_based route is temporarily disabled, allowing flexibility to enable or disable routes based on current compliance or application needs.

### Summary

With the "Geo_Based_Guideline" configuration loaded from a predefined JSON file, this setup directs:

  - Geolocation-Based Traffic: Routes traffic based on IP networks to specific regional destinations (e.g., US_Regions, EU_Regions).

  - Compliance-Based Traffic: Directs traffic requiring GDPR compliance to servers tagged with GDPR_Compliant.

This recipe demonstrates an efficient way to define and reuse routing guidelines for similar geolocation and compliance scenarios across multiple deployments by using a Routing Guideline imported from a JSON variable. This approach is ideal for scenarios where consistent routing configurations are needed across environments.

## Recipe 4: ClusterSet: Load Balancing and Resource Management

Load balancing and resource management guidelines help distribute traffic based on server roles and specific user access levels, optimizing resource usage and providing high availability. This recipe demonstrates how to import a routing guideline from a JSON file stored locally on your computer, allowing for predefined configurations that can be easily reused.

### Step 1: Create the JSON File for the Routing Guideline
Save the following JSON configuration in a file, e.g., load_balancing_guideline.json. This guideline directs read-only traffic to secondary and read replica servers while reserving write operations for the primary server, optimizing both resource usage and load distribution.

```
{
    "destinations": [
        {
            "match": "$.server.clusterRole = PRIMARY AND $.server.memberRole = READ_REPLICA",
            "name": "ReadReplica"
        },
        {
            "match": "$.server.clusterRole = PRIMARY AND $.server.memberRole = SECONDARY",
            "name": "Secondary"
        },
        {
            "match": "$.server.clusterRole = PRIMARY AND $.server.memberRole = PRIMARY",
            "name": "Primary"
        }
    ],
    "name": "Load_Balancing_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Secondary",
                        "ReadReplica"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                },
                {
                    "classes": [
                        "Primary"
                    ],
                    "strategy": "round-robin",
                    "priority": 1
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort = $.router.port.ro AND $.session.user = 'readonly_user'",
            "name": "ro"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Primary"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort in ($.router.port.rw, $.router.port.rw_split) AND $.session.user = 'admin_user'",
            "name": "rw"
        }
    ],
    "version": "1.1"
}
```

### Step 2: Import the Routing Guideline from the JSON File

To import the predefined JSON file into your cluster, use the importRoutingGuideline command. This method is efficient for deploying complex routing setups across environments, as it eliminates the need to manually add each destination and route.

```
// Import the routing guideline from the JSON file
rg2 = clusterset.import_routing_guideline("/path/to/load_balancing_guideline.json");
```

**NOTE**: Guidelines can be exported to JSON files with `.export(file_path)`.

### Summary

With the Load_Balancing_Guideline in place, this setup ensures:

  - Read-Only Traffic: Directs sessions using the "readonly_user" account to secondary and read replica nodes in a round-robin fashion, falling back to the primary if necessary.

  - Read-Write Traffic: Routes sessions using the admin_user account to the primary node, ensuring write operations are isolated to the primary server.

This configuration optimizes resource allocation by distributing read-only traffic across available replicas while preserving primary node resources for
write operations. Importing guidelines from JSON files enables you to quickly deploy consistent routing configurations across multiple topologies, ensuring effective load balancing and resource management.

## Recipe 5: ClusterSet: Application-Specific and Schema-Based Routing

Application-specific and schema-based routing allows routing guidelines to direct traffic to specific clusters or cluster members based on the application schema or other session details. This configuration is especially useful for vertically partitioned setups, where different schemas are managed by separate clusters to optimize performance and organization.

### JSON Document

```
{
    "destinations": [
        {
            "match": "$.server.clusterRole = REPLICA AND $.server.memberRole = PRIMARY AND $.server.clusterName = 'AppCluster'",
            "name": "App_ClusterSet_Primary_Replica"
        },
        {
            "match": "$.server.clusterRole = REPLICA AND $.server.memberRole = SECONDARY AND $.server.clusterName = 'AppCluster'",
            "name": "App_ClusterSet_Secondary_Replica"
        },
        {
            "match": "$.server.clusterRole = PRIMARY AND $.server.memberRole = PRIMARY",
            "name": "Data_ClusterSet_Primary_Primary"
        },
        {
            "match": "$.server.clusterRole = PRIMARY AND $.server.memberRole = SECONDARY",
            "name": "Data_ClusterSet_Secondary_Primary"
        }
    ],
    "name": "Vertical_Partitioning_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "App_ClusterSet_Primary_Replica",
                        "App_ClusterSet_Secondary_Replica"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.schema = 'app_schema'",
            "name": "app_schema_routing"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Data_ClusterSet_Primary_Primary",
                        "Data_ClusterSet_Secondary_Primary"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.schema = 'data_schema'",
            "name": "data_schema_routing"
        }
    ],
    "version": "1.1"
}
```

### Summary

With the Vertical_Partitioning_Guideline in place:

  - Application Schema Traffic: Sessions using app_schema are directed to the AppCluster, with a round-robin strategy across primary and secondary members.

  - Data Schema Traffic: Sessions using data_schema are directed to the main data cluster (Primary), distributed round-robin style between primary and secondary members.

This setup enables efficient traffic management across clusters tailored for specific application requirements, improving performance and simplifying database organization for vertically partitioned environments.


## Recipe 6: MySQL Version Specific Routing

MySQL Version Specific Routing is useful when certain applications or sessions need to connect to servers with a specific MySQL version. This can be essential for compatibility or testing purposes. This guideline directs read-write and read-only traffic to servers with specific MySQL versions, allowing precise version-based traffic management.

### JSON Document

```
{
    "destinations": [
        {
            "match": "$.server.version = 80403",
            "name": "MySQL_8_4_3"
        },
        {
            "match": "$.server.version = 80039",
            "name": "MySQL_8_0_39"
        }
    ],
    "name": "Version_Specific_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "MySQL_8_4_3"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort IN ($.router.port.rw, $.router.port.rw_split)",
            "name": "rw_traffic_to_8_4_3"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "MySQL_8_0_39"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.targetPort = $.router.port.ro",
            "name": "ro_traffic_to_8_0_39"
        }
    ],
    "version": "1.1"
}
```

### Summary

With the Version_Specific_Guideline in place:

  - Read-Write Traffic: Routes sessions on read-write ports (rw, rw_split) to servers running MySQL version 8.4.3, prioritizing them as first-available.

  - Read-Only Traffic: Routes sessions on the read-only port to servers running MySQL version 8.0.39 as first-available.

This configuration enables fine-grained traffic routing based on MySQL version, ensuring version-specific compatibility for various applications or testing environments.

## Recipe 7: Custom Tag-Based Routing and Performance-Based Routing

Custom tag-based and performance-based routing enables traffic routing based on server tags, such as performance levels or custom compliance attributes. This recipe uses tags to route critical application traffic to high-performance servers and directs compliance-related sessions based on specific user attributes.

### JSON Document

```
{
    "destinations": [
        {
            "match": "$.server.tags.performance = 'high'",
            "name": "High_Performance"
        },
        {
            "match": "$.server.tags.performance = 'low'",
            "name": "Low_Performance"
        },
        {
            "match": "$.server.tags.type = 'compliance'",
            "name": "Compliance_Tag"
        }
    ],
    "name": "Tag_Performance_Based_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "High_Performance",
                        "Low_Performance"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.connectAttrs.app = 'critical'",
            "name": "app_critical_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Compliance_Tag"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.user in ('admin', 'finance')",
            "name": "admin_finance_traffic"
        }
    ],
    "version": "1.1"
}
```

### Summary

With the Tag_Performance_Based_Guideline in place:

  - Critical Application Traffic: Routes sessions with the app attribute set to "critical" to servers tagged for high or low performance, prioritizing High_Performance nodes using a first-available strategy.

  - Compliance-Related Traffic: Routes sessions for admin and finance users to servers tagged with Compliance_Tag using a round-robin strategy to balance compliance-related load.

This setup enables performance-based and custom tag-based routing, directing specific applications and user sessions to the most appropriate resources based on performance needs or compliance attributes.


## Recipe 8: Testing, Staging, and Session Affinity

In environments with distinct stages such as testing, staging, and production, routing guidelines can direct traffic based on these designations, ensuring that different sessions are routed to the correct environment. Additionally, session affinity routes traffic from specific users to maintain session persistence across requests.

### JSON Document

```
{
    "destinations": [
        {
            "match": "$.server.tags.environment = 'production'",
            "name": "Production_Servers"
        },
        {
            "match": "$.server.tags.environment = 'staging'",
            "name": "Staging_Servers"
        },
        {
            "match": "$.server.tags.environment = 'testing'",
            "name": "Testing_Servers"
        }
    ],
    "name": "Testing_Stage_Session_Guideline",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Testing_Servers"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.randomValue < 0.1",
            "name": "testing_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Staging_Servers"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.randomValue >= 0.1 AND $.session.randomValue < 0.3",
            "name": "staging_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Production_Servers"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.randomValue >= 0.3",
            "name": "production_traffic"
        },
        {
            "connectionSharingAllowed": false,
            "destinations": [
                {
                    "classes": [
                        "Production_Servers",
                        "Staging_Servers",
                        "Testing_Servers"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.user = 'persistent_user'",
            "name": "session_affinity"
        }
    ],
    "version": "1.1"
}
```

### Summary

With the Testing_Stage_Session_Guideline in place:

  - Testing Traffic: Routes a small percentage (e.g., randomValue < 0.1) of requests to testing servers, allowing specific sessions to be tested without affecting other environments.

  - Staging Traffic: Routes moderate traffic (e.g., 0.1 <= randomValue < 0.3) to staging servers for pre-production validation.

  - Production Traffic: Routes remaining sessions to production servers, ensuring stable operation for production workloads.

  - Session Affinity: Routes all traffic from persistent_user to maintain session continuity across environments, with traffic distributed among all environments using round-robin.

This setup effectively partitions traffic based on environment, supports testing and staging, and provides session persistence where needed.

## Recipe 9: Client characteristics Routing

Client characteristics routing allows traffic to be directed based on specific attributes of the client session, such as operating system, platform, license type, or unique identifiers. This setup is particularly useful for managing resources in environments with diverse client requirements, ensuring sessions are routed to servers optimized for those characteristics.

### JSON Document

```
{
    "destinations": [
        {
            "match": "$.server.tags.backup = 'true'",
            "name": "Backup_Servers"
        },
        {
            "match": "$.server.tags.os = 'Linux'",
            "name": "Linux_Servers"
        },
        {
            "match": "$.server.tags.platform = 'x86_64'",
            "name": "x86_64_Servers"
        },
        {
            "match": "$.server.tags.license = 'Commercial'",
            "name": "Commercial_Servers"
        },
        {
            "match": "$.server.tags.test = 'true'",
            "name": "Testing_Servers"
        }
    ],
    "name": "Comprehensive_ConnectAttrs_Routing",
    "routes": [
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Linux_Servers"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.connectAttrs._os = 'Linux'",
            "name": "linux_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "x86_64_Servers"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.connectAttrs._platform = 'x86_64'",
            "name": "x86_64_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Backup_Servers"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.connectAttrs.program_name = 'mysqldump'",
            "name": "backup_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Commercial_Servers"
                    ],
                    "strategy": "round-robin",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.schema = 'audit'",
            "name": "commercial_traffic"
        },
        {
            "connectionSharingAllowed": true,
            "destinations": [
                {
                    "classes": [
                        "Testing_Servers"
                    ],
                    "strategy": "first-available",
                    "priority": 0
                }
            ],
            "enabled": true,
            "match": "$.session.user = 'test_user'",
            "name": "testing_traffic"
        }
    ],
    "version": "1.1"
}
```

### Summary

With the Comprehensive_ConnectAttrs_Routing in place:

  - linux_traffic: Routes sessions where the "_os" connection attribute is "Linux" to servers running on Linux ("Linux_Servers"), distributing connections in a round-robin fashion.

  - x86_64_traffic: Routes sessions with the "_platform" attribute set to "x86_64" to "x86_64_Servers", using a first-available strategy.

  - backup_traffic: Routes sessions coming from "mysqldump" (connectAttrs.program_name = 'mysqldump') to the "Backup_Servers".

  - Commercial Traffic: Routes sessions using the 'audit' schema to servers designated as "Commercial_Servers".

  - Testing Traffic: Routes specific test sessions ($.session.user = 'test_user') to servers tagged for testing ("Testing_Servers").

This guideline provides flexibility to route traffic based on client-specific attributes, enabling targeted resource allocation and optimization for diverse client characteristics.
