-
Notifications
You must be signed in to change notification settings - Fork 2
Update docs for ToolHive v0.12.3–v0.13.0 #641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -439,6 +439,41 @@ For more details about a specific MCP server: | |||||||||||||||||||||||||||||||||||||||||||||||||||
| kubectl -n <NAMESPACE> describe mcpserver <NAME> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Horizontal scaling | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| MCPServer creates two separate Deployments: one for the proxy runner and one for | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| the MCP server backend. You can scale each independently: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `spec.replicas` controls the proxy runner pod count | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `spec.backendReplicas` controls the backend MCP server pod count | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```yaml title="MCPServer resource" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| spec: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| replicas: 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| backendReplicas: 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| sessionStorage: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider: redis | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| address: redis-master.toolhive-system.svc.cluster.local:6379 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| db: 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| keyPrefix: mcp-sessions | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| passwordRef: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: redis-secret | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| key: password | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| When running multiple replicas, configure | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Redis session storage](./redis-session-storage.mdx) so that sessions are shared | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| across pods. If you omit `replicas` or `backendReplicas`, the operator defers | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing guidance on mixing The doc states each can be scaled independently, but doesn't say what the meaningful combinations are. For example: is scaling only the proxy useful if there's one backend? What happens if
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After digging into the operator source, here's what each layer does and the meaningful combinations: Architecture (from the code):
Suggested addition after the bullet list at line 448:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| replica management to an HPA or other external controller. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No mention of connection draining during scale-down The doc covers scale-out but is silent on scale-in. For MCP servers with long-lived SSE or streaming connections, abrupt pod termination can drop active sessions. Is there a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dug into the operator source. Here's the full picture: What the operator does:
Suggested addition at the end of the horizontal scaling section: :::note[Connection draining on scale-down]
When a proxy runner pod is terminated (scale-in, rolling update, or node
eviction), Kubernetes sends SIGTERM and the proxy drains in-flight requests
for up to 30 seconds before force-closing connections. The grace period and
drain timeout are both 30 seconds with no headroom, so long-lived SSE or
streaming connections may be dropped if they exceed the drain window.
No preStop hook is injected by the operator. If your workload requires
additional time — for example, to let kube-proxy propagate endpoint removal
before the pod stops accepting traffic — override `terminationGracePeriodSeconds`
via `podTemplateSpec`:
```yaml
spec:
podTemplateSpec:
spec:
terminationGracePeriodSeconds: 60The same 30-second default applies to the backend StatefulSet and to |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| :::warning[Stdio transport limitation] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Backends using the `stdio` transport are limited to a single replica. The | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| operator rejects configurations with `backendReplicas` greater than 1 for stdio | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| backends. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Next steps | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Connect clients to your MCP servers](./connect-clients.mdx) from outside the | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -455,6 +490,8 @@ kubectl -n <NAMESPACE> describe mcpserver <NAME> | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Kubernetes CRD reference](../reference/crd-spec.md#apiv1alpha1mcpserver) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Reference for the `MCPServer` Custom Resource Definition (CRD) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [vMCP scaling and performance](../guides-vmcp/scaling-and-performance.mdx) - | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Scale Virtual MCP Server deployments | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Deploy the operator](./deploy-operator.mdx) - Install the ToolHive operator | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Build MCP containers](../guides-cli/build-containers.mdx) - Create custom MCP | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| server container images | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ backend MCP servers, handling dependencies and collecting results. | |||||||||||||||||||||||||||
| wait for their prerequisites | ||||||||||||||||||||||||||||
| - **Template expansion**: Dynamic arguments using step outputs | ||||||||||||||||||||||||||||
| - **Elicitation**: Request user input mid-workflow (approval gates, choices) | ||||||||||||||||||||||||||||
| - **Iteration**: Loop over collections with forEach steps | ||||||||||||||||||||||||||||
| - **Error handling**: Configurable abort, continue, or retry behavior | ||||||||||||||||||||||||||||
| - **Timeouts**: Workflow and per-step timeout configuration | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
@@ -290,7 +291,7 @@ spec: | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### Steps | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Each step can be a tool call or an elicitation: | ||||||||||||||||||||||||||||
| Each step can be a tool call, an elicitation, or a forEach loop: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ```yaml title="VirtualMCPServer resource" | ||||||||||||||||||||||||||||
| spec: | ||||||||||||||||||||||||||||
|
|
@@ -344,6 +345,62 @@ spec: | |||||||||||||||||||||||||||
| timeout: '5m' | ||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### forEach steps | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Iterate over a collection from a previous step's output and execute a tool call | ||||||||||||||||||||||||||||
| for each item: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ```yaml title="VirtualMCPServer resource" | ||||||||||||||||||||||||||||
| spec: | ||||||||||||||||||||||||||||
| config: | ||||||||||||||||||||||||||||
| compositeTools: | ||||||||||||||||||||||||||||
| - name: scan_repositories | ||||||||||||||||||||||||||||
| description: Check each repository for security advisories | ||||||||||||||||||||||||||||
| parameters: | ||||||||||||||||||||||||||||
| type: object | ||||||||||||||||||||||||||||
| properties: | ||||||||||||||||||||||||||||
| org: | ||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||
| required: | ||||||||||||||||||||||||||||
| - org | ||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||
| - id: list_repos | ||||||||||||||||||||||||||||
| tool: github_list_repos | ||||||||||||||||||||||||||||
| arguments: | ||||||||||||||||||||||||||||
| org: '{{.params.org}}' | ||||||||||||||||||||||||||||
| # highlight-start | ||||||||||||||||||||||||||||
| - id: check_advisories | ||||||||||||||||||||||||||||
| type: forEach | ||||||||||||||||||||||||||||
| collection: '{{json .steps.list_repos.output.repositories}}' | ||||||||||||||||||||||||||||
| itemVar: repo | ||||||||||||||||||||||||||||
| maxParallel: 5 | ||||||||||||||||||||||||||||
| step: | ||||||||||||||||||||||||||||
| type: tool | ||||||||||||||||||||||||||||
| tool: github_list_security_advisories | ||||||||||||||||||||||||||||
| arguments: | ||||||||||||||||||||||||||||
| repo: '{{.forEach.repo.name}}' | ||||||||||||||||||||||||||||
| onError: | ||||||||||||||||||||||||||||
| action: continue | ||||||||||||||||||||||||||||
| dependsOn: [list_repos] | ||||||||||||||||||||||||||||
| # highlight-end | ||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| **forEach fields:** | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| | Field | Description | Default | | ||||||||||||||||||||||||||||
| | --------------- | ----------------------------------------------------- | ------- | | ||||||||||||||||||||||||||||
| | `collection` | Template expression that produces an array | — | | ||||||||||||||||||||||||||||
| | `itemVar` | Variable name for the current item | item | | ||||||||||||||||||||||||||||
| | `maxParallel` | Maximum concurrent iterations (max 50) | 10 | | ||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confirmed by The note fits right after the template access paragraph (line 402), before
Suggested change
|
||||||||||||||||||||||||||||
| | `maxIterations` | Maximum total iterations (max 1000) | 100 | | ||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No guidance on timeout interaction with At
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can take the scalability changes |
||||||||||||||||||||||||||||
| | `step` | Inner step definition (tool call to execute per item) | — | | ||||||||||||||||||||||||||||
| | `onError` | Error handling: `abort` (stop) or `continue` (skip) | abort | | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Access the current item inside the inner step using | ||||||||||||||||||||||||||||
| `{{.forEach.<itemVar>.<field>}}`. In the example above, `{{.forEach.repo.name}}` | ||||||||||||||||||||||||||||
| accesses the `name` field of the current repository. You can also use | ||||||||||||||||||||||||||||
| `{{.forEach.index}}` to access the zero-based iteration index. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### Error handling | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Configure behavior when steps fail: | ||||||||||||||||||||||||||||
|
|
@@ -507,13 +564,16 @@ without defaultResults defined | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Access workflow context in arguments: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| | Template | Description | | ||||||||||||||||||||||||||||
| | --------------------------- | ------------------------------------------ | | ||||||||||||||||||||||||||||
| | `{{.params.name}}` | Input parameter | | ||||||||||||||||||||||||||||
| | `{{.steps.id.output}}` | Step output (map) | | ||||||||||||||||||||||||||||
| | `{{.steps.id.output.text}}` | Text content from step output | | ||||||||||||||||||||||||||||
| | `{{.steps.id.content}}` | Elicitation response content | | ||||||||||||||||||||||||||||
| | `{{.steps.id.action}}` | Elicitation action (accept/decline/cancel) | | ||||||||||||||||||||||||||||
| | Template | Description | | ||||||||||||||||||||||||||||
| | -------------------------------- | ------------------------------------------ | | ||||||||||||||||||||||||||||
| | `{{.params.name}}` | Input parameter | | ||||||||||||||||||||||||||||
| | `{{.steps.id.output}}` | Step output (map) | | ||||||||||||||||||||||||||||
| | `{{.steps.id.output.text}}` | Text content from step output | | ||||||||||||||||||||||||||||
| | `{{.steps.id.content}}` | Elicitation response content | | ||||||||||||||||||||||||||||
| | `{{.steps.id.action}}` | Elicitation action (accept/decline/cancel) | | ||||||||||||||||||||||||||||
| | `{{.forEach.<itemVar>}}` | Current forEach item | | ||||||||||||||||||||||||||||
| | `{{.forEach.<itemVar>.<field>}}` | Field on current forEach item | | ||||||||||||||||||||||||||||
| | `{{.forEach.index}}` | Zero-based iteration index | | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### Template functions | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,10 @@ description: | |||||||||||||||||||
| How to scale Virtual MCP Server deployments vertically and horizontally. | ||||||||||||||||||||
| --- | ||||||||||||||||||||
|
|
||||||||||||||||||||
| This guide explains how to scale Virtual MCP Server (vMCP) deployments. | ||||||||||||||||||||
| This guide explains how to scale Virtual MCP Server (vMCP) deployments. For | ||||||||||||||||||||
| MCPServer scaling, see | ||||||||||||||||||||
| [Horizontal scaling](../guides-k8s/run-mcp-k8s.mdx#horizontal-scaling) in the | ||||||||||||||||||||
| Kubernetes operator guide. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Vertical scaling | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -37,24 +40,60 @@ higher request volumes. | |||||||||||||||||||
|
|
||||||||||||||||||||
| ### How to scale horizontally | ||||||||||||||||||||
|
|
||||||||||||||||||||
| The VirtualMCPServer CRD does not have a `replicas` field. The operator creates | ||||||||||||||||||||
| a Deployment named `vmcp-<NAME>` (where `<NAME>` is your VirtualMCPServer name) | ||||||||||||||||||||
| with 1 replica and preserves the replicas count, allowing you to manage scaling | ||||||||||||||||||||
| separately. | ||||||||||||||||||||
| Set the `replicas` field in your VirtualMCPServer spec to control the number of | ||||||||||||||||||||
| vMCP pods: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```yaml title="VirtualMCPServer resource" | ||||||||||||||||||||
| spec: | ||||||||||||||||||||
| replicas: 3 | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| If you omit `replicas`, the operator defers replica management to an HPA or | ||||||||||||||||||||
| other external controller. You can also scale manually or with an HPA: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Option 1: Manual scaling** | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| kubectl scale deployment vmcp-<vmcp-name> -n <NAMESPACE> --replicas=3 | ||||||||||||||||||||
| kubectl scale deployment vmcp-<VMCP_NAME> -n <NAMESPACE> --replicas=3 | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Option 2: Autoscaling with HPA** | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| kubectl autoscale deployment vmcp-<vmcp-name> -n <NAMESPACE> \ | ||||||||||||||||||||
| kubectl autoscale deployment vmcp-<VMCP_NAME> -n <NAMESPACE> \ | ||||||||||||||||||||
| --min=2 --max=5 --cpu-percent=70 | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ### Session storage for multi-replica deployments | ||||||||||||||||||||
|
|
||||||||||||||||||||
| When running multiple replicas, configure Redis session storage so that sessions | ||||||||||||||||||||
| are shared across pods. Without session storage, a request routed to a different | ||||||||||||||||||||
| replica than the one that established the session will fail. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```yaml title="VirtualMCPServer resource" | ||||||||||||||||||||
| spec: | ||||||||||||||||||||
| replicas: 3 | ||||||||||||||||||||
| sessionStorage: | ||||||||||||||||||||
| provider: redis | ||||||||||||||||||||
| address: redis-master.toolhive-system.svc.cluster.local:6379 | ||||||||||||||||||||
| db: 0 | ||||||||||||||||||||
| keyPrefix: vmcp-sessions | ||||||||||||||||||||
| passwordRef: | ||||||||||||||||||||
| name: redis-secret | ||||||||||||||||||||
| key: password | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| See [Redis Sentinel session storage](../guides-k8s/redis-session-storage.mdx) | ||||||||||||||||||||
| for a complete Redis deployment guide. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| :::warning | ||||||||||||||||||||
|
|
||||||||||||||||||||
| If you configure multiple replicas without session storage, the operator sets a | ||||||||||||||||||||
| `SessionStorageMissingForReplicas` status condition on the resource. Ensure | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Advisory-only: the operator does not block the scale-out I checked the operator source ( The current wording is accurate but incomplete — readers may assume the condition is a rejection. It should be explicit that the operator still applies the replica count:
Suggested change
One additional nit: the condition type shown in |
||||||||||||||||||||
| Redis is available before scaling beyond a single replica. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ::: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ### When horizontal scaling is challenging | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Horizontal scaling works well for **stateless backends** (fetch, search, | ||||||||||||||||||||
|
|
@@ -63,22 +102,22 @@ read-only operations) where sessions can be resumed on any instance. | |||||||||||||||||||
| However, **stateful backends** make horizontal scaling difficult: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - **Stateful backends** (Playwright browser sessions, database connections, file | ||||||||||||||||||||
| system operations) require requests to be routed to the same vMCP instance | ||||||||||||||||||||
| that established the session | ||||||||||||||||||||
| system operations) require requests to be routed to the same instance that | ||||||||||||||||||||
| established the session | ||||||||||||||||||||
| - Session resumption may not work reliably for stateful backends | ||||||||||||||||||||
|
|
||||||||||||||||||||
| The `VirtualMCPServer` CRD includes a `sessionAffinity` field that controls how | ||||||||||||||||||||
| the Kubernetes Service routes repeated client connections. By default, it uses | ||||||||||||||||||||
| `ClientIP` affinity, which routes connections from the same client IP to the | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The doc presents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The CRD confirms Suggested replacement for the
Suggested change
:::warning[ClientIP affinity is unreliable behind NAT or shared egress IPs]
For stateless backends, disable affinity so the Service load-balances freely: spec:
sessionAffinity: NoneFor stateful backends where true per-session routing is required, ::: |
||||||||||||||||||||
| same pod. You can configure this using the `sessionAffinity` field: | ||||||||||||||||||||
| same pod: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```yaml | ||||||||||||||||||||
| spec: | ||||||||||||||||||||
| sessionAffinity: ClientIP # default | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| For stateful backends, vertical scaling or dedicated vMCP instances per team/use | ||||||||||||||||||||
| case are recommended instead of horizontal scaling. | ||||||||||||||||||||
| For stateful backends, vertical scaling or dedicated instances per team/use case | ||||||||||||||||||||
| are recommended instead of horizontal scaling. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Next steps | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded Redis address implies a specific namespace
The example uses
redis-master.toolhive-system.svc.cluster.localas the address. Users deploying Redis in a different namespace (or using an external Redis) won't get any hint that this needs to change — they'll just have a silently misconfigured deployment. Worth adding a comment or callout that this is an example address and should match the actual Redis Service location.