Route Collision Guard
Prevents route conflicts when publishing APIs by checking if a route is already in use by another service, ensuring routing stability across the platform.
Overview
The Route Collision Guard is an internal, fail-safe mechanism that prevents different services from unintentionally claiming the same API route. It solves the problem of "route stealing," where publishing or activating one service could silently reassign a live API route from another service, leading to unpredictable request routing and service outages.
This guard runs as a prerequisite check within the transaction that publishes or updates a service's routes. It examines the set of routes a service is about to publish and verifies that none of them are already active and owned by a different service within the same tenant.
If a conflict is detected, the guard throws an exception that aborts the entire publication process. This ensures that the existing, live route remains pointed to its original owner, and the new service is not activated. If no conflicts are found, the publication proceeds.
How it Works
The route collision check is triggered whenever a service's routes are published, which can occur during service version activation or a manual synchronization operation. The process is designed to be atomic and fail-closed, preserving the integrity of the existing routing table.
sequenceDiagram
participant P as API Publisher
participant A as Admin Platform
participant G as Route Collision Guard
participant D as Database
P->>A: Activate Service Version
A->>G: assertNoCrossServiceCollision(serviceId, candidates)
loop For each candidate route
G->>D: Query for conflicting route
alt Conflict exists
D-->>G: Return existing owner's service ID
G-->>A: throw RouteCollisionException
A-->>P: Error: Route conflict detected
else No conflict
D-->>G: Return empty result
end
end
G-->>A: Return (no exception)
A->>D: Write new routes to s2r_runtime_route table
D-->>A: Commit transaction
A-->>P: Success: Service activatedThe mechanism follows these steps:
-
An API publisher initiates an action that publishes a service's routes (e.g., activating a new version).
-
Before writing to the
s2r_runtime_routetable, the platform calls theRouteCollisionGuard.assertNoCrossServiceCollisionmethod. This method receives the ID of the service being published and a list of its candidate routes. -
The guard iterates through each candidate route key. A route key is defined by its
direction,environment,restMethod, andrestPath. -
For each key, the guard executes a SQL query against the
s2r_runtime_routetable to find any active routes that match the key but are owned by a different service.select rr.service_id as existing_service_id, s.service_key as existing_service_key from s2r_runtime_route rr join s2r_service s on s.id = rr.service_id where rr.direction = ? and rr.environment = ? and rr.rest_method = ? and rr.rest_path = ? and rr.enabled = true and rr.service_id <> ? and rr.tenant_id = ? -- Simplified representation of the tenant scope filter limit 1 -
Conflict Path: If the query returns a result, it means a conflicting route exists. The guard immediately throws a
RouteCollisionException, which includes details about the conflicting route and the service that currently owns it. This exception causes the parent database transaction to roll back, preventing any changes to the routing table. -
Success Path: If the query finds no conflicting routes for any of the candidates, the
assertNoCrossServiceCollisionmethod completes without an exception. The publication process then proceeds to write the new route configurations to the database.
Collision Check Scope
The guard's logic is narrowly scoped to prevent accidental cross-service conflicts while permitting legitimate operations. The following conditions apply:
- Self-Updates: A service can always republish its own routes. The check explicitly ignores routes owned by the same service that is being published. This allows for service version updates and rollbacks.
- Tenant Isolation: Route uniqueness is enforced on a per-tenant basis. Two different tenants can own a route with the same path and method without causing a collision. The check is always filtered to the tenant context of the service being published.
- Directionality: A
PUBLISHroute and aCONSUMEroute with the same path do not collide. Thedirectionis part of the unique key for a route. - Disabled Routes: The guard only checks against active routes (
enabled = true). If a service's routes are disabled, another service can claim those paths without conflict.
API Reference
The RouteCollisionGuard exposes a single method and uses a data record to define candidate routes.
Method: assertNoCrossServiceCollision
Checks a list of candidate routes for conflicts with existing, active routes owned by other services. If a conflict is found, it throws an exception to halt the publication process.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
owningServiceId | UUID | Yes | The unique identifier of the service being published. |
candidates | List<RouteKey> | Yes | A list of route keys the service intends to publish. |
Throws
RouteCollisionException: Thrown on the first colliding key found. The publication transaction is rolled back.
Data Structure: RouteKey
A record that represents the unique key of a candidate runtime route.
| Field | Type | Required | Description |
|---|---|---|---|
direction | String | Yes | The direction of the route (e.g., PUBLISH, CONSUME). |
environment | String | Yes | The environment where the route will be active (e.g., production). |
restMethod | String | Yes | The HTTP method of the route (e.g., GET, POST). |
restPath | String | Yes | The URL path of the route (e.g., /v1/widgets). |
Troubleshooting
RouteCollisionException
This exception is the primary failure mode for the route collision guard.
- Condition: An API publisher attempts to activate or publish a service, but one or more of its defined routes are already in use by another active service within the same tenant.
- Cause: The combination of
direction,environment,restMethod, andrestPathfor a candidate route matches anenabledroute in thes2r_runtime_routetable that is associated with a differentservice_id. - Resolution: The API publisher must resolve the conflict. The exception details identify the conflicting route and the
service_keyof the service that currently owns it. To proceed, the publisher must either:- Modify the service definition to change the conflicting route's path, method, or direction.
- Decommission or disable the other service that currently owns the route, thereby freeing it for use.
