Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ config:
no-hard-tabs: false
no-inline-html: false
no-multiple-blanks: false
max-one-sentence-per-line: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙏

customRules:
- "markdownlint-rule-max-one-sentence-per-line"
fix: false
Expand Down
1 change: 0 additions & 1 deletion pages/spicedb/concepts/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"consistency": "Consistency",
"datastores": "Datastores",
"datastore-migrations": "Datastore Migrations",
"dispatch": "Dispatch",
"reflection-apis": "Reflection APIs",
"watch": "Watching Changes"
}
57 changes: 0 additions & 57 deletions pages/spicedb/concepts/dispatch.mdx

This file was deleted.

1 change: 0 additions & 1 deletion pages/spicedb/getting-started/first-steps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import { InlinePlayground } from '@/components/playground'
<Cards>
<Card arrow={true} title="Consistency" href="../concepts/consistency" />
<Card arrow={true} title="Caveats" href="../concepts/caveats" />
<Card arrow={true} title="Dispatch" href="../concepts/dispatch" />
</Cards>

### Dive into some videos
Expand Down
1 change: 1 addition & 0 deletions pages/spicedb/ops/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"deploying-spicedb-operator": "Deploying the SpiceDB Kubernetes Operator",
"eks": "Deploying to AWS EKS",
"data": "Writing data to SpiceDB",
"performance": "Improving Performance",
"observability": "Observability Tooling",
"ai-agent-authorization": "Authorization for AI Agents",
"secure-rag-pipelines": "Secure Your RAG Pipelines with Fine Grained Authorization"
Expand Down
6 changes: 3 additions & 3 deletions pages/spicedb/ops/eks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,13 @@ If the `spicedb-le-tls` secret is not present, follow this [troubleshooting guid
[Secret]: https://kubernetes.io/docs/concepts/configuration/secret
[troubleshooting guide]: https://cert-manager.io/docs/troubleshooting/acme/

### Configuring Dispatch TLS
### Configuring Cross-Pod TLS

SpiceDB [dispatches] work across instances in the same deployment via [gRPC].
SpiceDB will be more performant when cross-pod communication is enabled (see [performance]).
We'll be securing this pod-to-pod communication with its own internal-only certificate:

[gRPC]: https://grpc.io
[dispatches]: ../concepts/dispatch
[performance]: performance#by-enabling-cross-node-communication

```sh
kubectl apply --server-side -f - <<EOF
Expand Down
90 changes: 90 additions & 0 deletions pages/spicedb/ops/performance.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Callout } from 'nextra/components'

# Improving Performance
Copy link
Contributor Author

@miparnisari miparnisari Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that this doc now has 3 sections: dispatch, materialize, namespace cache

@josephschorr any other sections worth adding? we could (later) add a section on schema considerations for better performance


## By enabling cross-node communication

SpiceDB can be deployed in a clustered configuration where multiple nodes work together to serve API requests. In such a configuration, and for the CheckPermissions API, enabling a feature called **dispatch** allows nodes to break down one API request into smaller "questions" and forward those to other nodes within the cluster. This helps reduce latency and improve overall performance.

### How it works

Each SpiceDB node maintains an in-memory cache of permissions queries it has resolved in the past. When a new permissions query is encountered by one node, its answer may be present on another node, so SpiceDB will forward the request onward to the other node to check the shared cache.

For more details on how dispatching works, see the [Consistent Hash Load Balancing for gRPC] article.
Copy link
Contributor Author

@miparnisari miparnisari Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI i removed the architecture drawing since i felt that it didn't add much value and it looked oriented towards maintainers, not users

I'm not too happy on the level of detail that we've provided here but I also don't want to overwhelm people. I still don't know enough about dispatching to feel comfortable writing more. are there any details that a user of spicedb should know about implementation?


[consistent hash load balancing for grpc]: https://authzed.com/blog/consistent-hash-load-balancing-grpc/

### Configuration in Kubernetes environments

If using the [SpiceDB Operator], dispatching is enabled by default and no additional configuration is necessary.

If not using it, you need to set the following flag:

```sh
--dispatch-upstream-addr=kubernetes:///spicedb.default:50053
```

where `spicedb.default` is the Kubernetes `Service` in which SpiceDB is accessible.

<Callout type="info">
If you are deploying SpiceDB under Kubernetes, it is recommended to use the [SpiceDB Operator], which configures dispatching automatically.

[spicedb operator]: /spicedb/ops/operator
</Callout>

### Configuration in non-Kubernetes environments

<Callout type="warning">
Non-Kubernetes based dispatching relies upon DNS updates, which means it can become stale if DNS is changing. This is not recommended unless DNS updates are rare.
</Callout>

To enable dispatch, the following flags must be specified:

```sh
spicedb serve \
--dispatch-cluster-enabled=true \
--dispatch-upstream-addr=upstream-addr \
...
```

or via environment variables with the `SPICEDB_` prefix:

```sh
SPICEDB_DISPATCH_CLUSTER_ENABLED=true \
SPICEDB_DISPATCH_UPSTREAM_ADDR=upstream-addr \
spicedb serve ...
```

The `upstream-addr` should be the DNS address of the load balancer at which _all_ SpiceDB nodes are accessible at the default dispatch port of `:50053`.

## By enabling Materialize

[Materialize] is a separate service that allows for the precomputation of permission query results.

If Materialize is running, SpiceDB can dispatch sub-queries to Materialize, which can significantly speed up permission checks.

[Materialize]: /authzed/concepts/authzed-materialize

## By enabling the schema cache

The schema cache stores type definitions and caveat definitions to avoid repeatedly fetching schema information from the datastore.

SpiceDB offers two caching modes:

1. **Just-In-Time (JIT) Caching**: The default mode that loads definitions on-demand. Uses less memory, but it incurs a cold start penalty on first access to each definition.
2. **Watching Cache**: An experimental mode that proactively maintains an always-up-to-date cache. This mode uses more memory but avoids cold start penalties. It is recommended when there are frequent schema changes.
Comment on lines +74 to +75
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephschorr to confirm if this is accurate

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but will all be going away soon-ish once the new cache lands


To configure the schema cache, use the following flags:

```bash
# Enable namespace cache (default: true)
--ns-cache-enabled=true

# Maximum memory (default: 32 MiB)
--ns-cache-max-cost=32MiB

# Enable experimental watchable schema cache (default: false)
# When true: uses watching cache if datastore supports it
# When false: always uses JIT caching
--enable-experimental-watchable-schema-cache=false
```