You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: pages/best-practices/best-practices.mdx
+40-37Lines changed: 40 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,65 +1,68 @@
1
1
# Best Practices
2
2
3
-
###Rule Categories
3
+
## Rule Categories
4
4
5
-
####Priority A: Essential
5
+
### Priority A: Essential
6
6
7
7
The essential rules are the most important ones.
8
8
Use them to ensure that your SpiceDB cluster is performant, your schema is sane, and your authorization logic is sound.
9
9
Exceptions to these rules should be rare and well justified.
10
10
11
-
####Priority B: Strongly Recommended
11
+
### Priority B: Strongly Recommended
12
12
13
13
The strong recommendation rules will improve the schema design, developer experience, and performance of your SpiceDB cluster.
14
14
In most cases, these rules should be followed.
15
15
16
-
####Priority C: Recommended
16
+
### Priority C: Recommended
17
17
18
18
The recommended rules reflect how we would run our own systems, but may not apply to every use case and may not make sense in every situation.
19
19
Follow them if you can and ignore them if you can’t.
20
20
21
-
###Priority A Rules: Essential
21
+
## Priority A Rules: Essential
22
22
23
-
####Make sure your schema fails closed
23
+
### Make sure your schema fails closed
24
24
25
25
Tags: **schema**
26
26
27
27
This is related to the idea of using negation sparingly, and of phrasing your schema additively.
28
-
Give thought to what happens if your application fails to write a relation: should the user have access in that case? The answer is almost always `no`.
28
+
Give thought to what happens if your application fails to write a relation: should the user have access in that case?
29
+
The answer is almost always `no`.
29
30
30
-
####Tune Connections to Datastores
31
+
### Tune Connections to Datastores
31
32
32
33
Tags: **operations**
33
34
34
35
To size your SpiceDB connection pools, start by determining the maximum number of allowed connections based on the documentation for your selected datastore, divide that number by the number of SpiceDB pods you’ve deployed, then split it between read and write pools.
35
36
36
37
Use these values to set the `--datastore-conn-pool-read-max-open` and `--datastore-conn-pool-write-max-open` flags, and set the corresponding min values to half of each, adjusting as needed based on whether your workload leans more heavily on reads or writes.
37
38
38
-
####Test Your Schema
39
+
### Test Your Schema
39
40
40
41
Tags: **schema**
41
42
42
43
You should be testing the logic of your schema to ensure that it behaves the way you expect.
44
+
43
45
- For unit testing and TDD, use test relations + assertions and [zed validate](https://authzed.com/docs/spicedb/modeling/validation-testing-debugging#zed-validate).
44
46
- For snapshot testing, use test relations + expected relations and [zed validate](https://authzed.com/docs/spicedb/modeling/validation-testing-debugging#zed-validate).
45
47
- For integration testing, use the SpiceDB test server with spicedb [serve-testing](https://authzed.com/docs/spicedb/modeling/validation-testing-debugging#integration-test-server).
46
48
47
-
####Prefer Relations to Caveats
49
+
### Prefer Relations to Caveats
48
50
49
51
Tags: **schema**
50
52
51
53
If an authorization concept can be expressed using relations, it should be.
52
54
We provide caveats as an escape hatch; they should only be used for context that’s only available at request time, or else ABAC logic that cannot be expressed in terms of relationships.
53
55
54
56
Some examples:
57
+
55
58
- A banlist - this could be expressed as a list in caveat context, but it can also be expressed as a relation with negation.
56
59
- A notion of public vs internal - boolean flags seem like an obvious caveat use case, but they can also be expressed using self relations.
57
60
- Dynamic roles - these could be expressed as a list in caveats, and it’s not immediately obvious how to build them into a spicedb schema, but our [Google Cloud IAM example](https://authzed.com/blog/google-cloud-iam-modeling) shows how it’s possible.
58
61
59
62
This is because caveats come with a performance penalty.
60
63
A caveated relationship is both harder to cache and also slows down computation of the graph walk required to compute a permission.
61
64
62
-
####Make Your Writes Idempotent
65
+
### Make Your Writes Idempotent
63
66
64
67
Tags: **application**
65
68
@@ -68,7 +71,7 @@ As much as possible, we recommend that you use the `TOUCH` semantic for your wri
68
71
69
72
If you’re concerned about sequencing your writes, or your writes have dependencies, we recommend using preconditions.
70
73
71
-
####Don’t truncate your tables when running Postgres
74
+
### Don’t truncate your tables when running Postgres
72
75
73
76
Tags: **operations**
74
77
@@ -79,9 +82,9 @@ To ensure that every request, whether cached or not, gets a consistent point-in-
79
82
Some datastores provide this natively; in others we’ve implemented it on top of the datastore.
80
83
In Postgres, the implementation of MVCC depends on the internals of the transaction counter being stored as data in the tables, so if you truncate the relationships table you desync the transaction counter with the stored relationships.
81
84
82
-
###Priority B Rules: Strongly Recommended
85
+
## Priority B Rules: Strongly Recommended
83
86
84
-
####Understand your consistency needs
87
+
### Understand your consistency needs
85
88
86
89
Tags: **operations**
87
90
@@ -92,23 +95,23 @@ To change this value, set `--datastore-revision-quantization-interval` longer or
92
95
When it comes to write consistency, SpiceDB defaults to high safety, especially in distributed database writing scenarios, guaranteeing a visibility order.
93
96
Individual datastores may also allow a relaxation of this guarantee, based on your scenario; for example, [setting CockroachDB’s overlap strategy](https://authzed.com/docs/spicedb/concepts/datastores#overlap-strategy), trading some authorization visibility safety across domains for greatly increased write throughput.
94
97
95
-
####Use GRPC When Possible
98
+
### Use GRPC When Possible
96
99
97
100
Tags: **application**
98
101
99
102
SpiceDB can be configured to expose both an [HTTP API](https://authzed.com/docs/spicedb/getting-started/client-libraries#http-clients) and associated Swagger documentation.
100
103
While this can be helpful for initial exploration, we strongly recommend using one of our gRPC-based official client libraries if your networking and calling language support it.
101
104
gRPC is significantly more performant and lower-latency than HTTP, and client-streaming services like ImportBulk can’t be used with the HTTP API.
102
105
103
-
####Keep Permission Logic in SpiceDB
106
+
### Keep Permission Logic in SpiceDB
104
107
105
108
Tags: **schema**
106
109
107
110
One of the big benefits to using a centralized authorization system like SpiceDB is that there's one place to look for your authorization logic, and authorization logic isn't duplicated across services.
108
111
It can be tempting to define the authorization logic for an endpoint as being the `AND` or `OR` of the checks of other permissions, especially when the alternative is writing a new schema.
109
112
However, this increases the likelihood of drift across your system, hides the authorization logic for a system in that system's codebase, and increases the load on SpiceDB.
110
113
111
-
####Avoid Cycles in your Schema
114
+
### Avoid Cycles in your Schema
112
115
113
116
Tags: **schema**
114
117
@@ -142,7 +145,7 @@ definition group {
142
145
}
143
146
```
144
147
145
-
####Phrase Permissions Additively/Positively
148
+
### Phrase Permissions Additively/Positively
146
149
147
150
Tags: **schema**
148
151
@@ -153,15 +156,15 @@ This reduces the number of ways that permission logic can interact, and prevents
153
156
In concrete terms, that means use wildcards and negations sparingly.
154
157
Start with no access and build up; don’t start with full access and pare down.
155
158
156
-
####Use Unique Identifiers for Object Identifiers
159
+
### Use Unique Identifiers for Object Identifiers
157
160
158
161
Tags: **application**
159
162
160
163
Because you typically want to centralize your permissions in SpiceDB, that also means that most of the `IDs` of objects in SpiceDB are references to external entities.
161
-
These external entities shouldn't overlap.
164
+
These external entities shouldn't overlap.
162
165
To that end, we recommend either using `UUIDs` or using another identifier from the upstream that you can be sure will be unique, such as the unique sub field assigned to a user token by your IDP.
163
166
164
-
####Avoid ReadRelationships API
167
+
### Avoid ReadRelationships API
165
168
166
169
Tags: **application**
167
170
@@ -170,7 +173,7 @@ Using it for permission logic is a code smell.
170
173
All checks and listing of IDs should use `Check`, `CheckBulk`, `LookupResources`, and `LookupSubjects`.
171
174
If you find yourself reaching for the `ReadRelationships` API for permission logic, there's probably a way to modify your schema to use one of the check APIs instead.
172
175
173
-
####Prefer CheckBulk To LookupResources
176
+
### Prefer CheckBulk To LookupResources
174
177
175
178
Tags: **application**
176
179
@@ -180,24 +183,24 @@ Where possible, we recommend `CheckBulk`, because its work is bounded to the lis
180
183
LookupResources generally requires a lot of work, causes a higher load, and subsequently has some of the highest latencies.
181
184
If you need its semantics but its performance is insufficient, we recommend checking out our [Materialize](https://authzed.com/products/authzed-materialize) offering.
182
185
183
-
###Priority C Rules: Recommended
186
+
## Priority C Rules: Recommended
184
187
185
-
####Treat Writing Schema like Writing DB Migrations
188
+
### Treat Writing Schema like Writing DB Migrations
186
189
187
190
Tags: **operations**
188
191
189
192
We recommend treating your SpiceDB schema as though it were a database migration.
190
193
Keep it in your codebase, test it before deployment, and write it to your SpiceDB cluster as a part of your continuous integration process.
191
194
This ensures that updates to your schema are properly controlled.
192
195
193
-
####Load Test
196
+
### Load Test
194
197
195
198
Tags: **operations**
196
199
197
200
To evaluate the performance and capabilities of your SpiceDB cluster and its underlying datastore, AuthZed provides [Thumper](https://github.com/authzed/thumper) — a load testing tool.
198
201
You can use Thumper to simulate workloads and validate schema updates before deploying them to a production environment.
199
202
200
-
####Use ZedTokens and “At Least As Fresh” for Best Caching
203
+
### Use ZedTokens and “At Least As Fresh” for Best Caching
201
204
202
205
Tags: **application**
203
206
@@ -207,15 +210,15 @@ If possible, we recommend using `at_least_as_fresh` with `ZedTokens` instead.
207
210
Capture the `ZedToken` returned by your initial request, then include it in all subsequent calls.
208
211
SpiceDB will guarantee you see a state at least as fresh as that token while still leveraging in-memory and datastore caches to deliver low-latency responses
209
212
210
-
####Prefer Checking Permissions Instead of Relationships
213
+
### Prefer Checking Permissions Instead of Relationships
211
214
212
215
Tags: **application**
213
216
214
217
It's possible to make a `Check` call with a relation as the permission.
215
218
Even in a simple schema, we recommend instead that you have a permission that points at the relation and to check the relation.
216
219
This is because if the logic of the check needs to change, it's easy to change the definition of a permission and difficult to change the definition of a relation (it often requires a data migration).
217
220
218
-
####Enable schema watch cache
221
+
### Enable schema watch cache
219
222
220
223
Tags: **operations**
221
224
@@ -226,15 +229,15 @@ While we recommend enabling this, it isn't enabled by default because it require
226
229
For Postgres, [`track_commit_timestamp`](https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-TRACK-COMMIT-TIMESTAMP) must be set to `on` for the Watch API to be enabled.
227
230
For Spanner, there are a maximum of 5 changefeeds available globally for a table, and this consumes one of them.
228
231
229
-
####Use the Operator
232
+
### Use the Operator
230
233
231
234
Tags: **operations**
232
235
233
236
To ensure seamless rollouts, upgrades, and schema migrations, it is recommended to use the SpiceDB Kubernetes Operator if you’re using Kubernetes.
234
237
The Operator automates many operational tasks and helps maintain consistency across environments.
235
238
You can find the official documentation for the SpiceDB operator [here](https://authzed.com/docs/spicedb/concepts/operator).
236
239
237
-
####Ensure that SpiceDB Can Talk To Itself
240
+
### Ensure that SpiceDB Can Talk To Itself
238
241
239
242
Tags: **operations**
240
243
@@ -246,43 +249,43 @@ In our experience, running SpiceDB on Kubernetes with our [Operator](https://aut
246
249
It’s possible to configure dispatch using DNS as well, but non-Kubernetes based dispatching relies upon DNS updates, which means it can become stale if DNS is changing.
247
250
This is not recommended unless DNS updates are rare.
248
251
249
-
####Choose the Right Load Balancer
252
+
### Choose the Right Load Balancer
250
253
251
254
Tags: **operations**
252
255
253
256
In our experience, TCP-level L4 load balancers play more nicely with gRPC clients than HTTP-level L7 load balancers.
254
257
For example, we’ve found that even though AWS Application Load Balancers purport to support gRPC, they have a tendency to drop connections and otherwise misbehave; AWS Network Load Balancers seem to work better.
255
258
256
-
####Use the Provided Metrics, Traces, and Profiles
259
+
### Use the Provided Metrics, Traces, and Profiles
257
260
258
261
Tags: **operations**
259
262
260
263
To gain deeper insights into the performance of your SpiceDB cluster, the pods expose both Prometheus metrics and `pprof` profiling endpoints.
261
264
You can also configure tracing to export data to compatible OpenTelemetry backends.
262
265
263
266
- Refer to the [SpiceDB Prometheus documentation](https://authzed.com/docs/spicedb/ops/observability#prometheus) for details on collecting metrics.
264
-
- AuthZed Cloud supports exporting metrics to Datadog via the official [AuthZed cloud datadog integration](https://docs.datadoghq.com/integrations/authzed_cloud/).
265
-
- To gain a complete picture of your SpiceDB cluster’s performance, it’s important to export metrics from the underlying datastore.
267
+
- AuthZed Cloud supports exporting metrics to Datadog via the official [AuthZed cloud datadog integration](https://docs.datadoghq.com/integrations/authzed_cloud/).
268
+
- To gain a complete picture of your SpiceDB cluster’s performance, it’s important to export metrics from the underlying datastore.
266
269
These metrics help identify potential bottlenecks and performance issues.
267
270
AuthZed Cloud provides access to both CockroachDB and PostgreSQL metrics via its cloud telemetry endpoints, enabling deeper visibility into database behavior.
268
271
- The [profiling documentation](https://authzed.com/docs/spicedb/ops/observability#profiling) explains how to use the pprof endpoints.
269
272
- The [tracing documentation](https://authzed.com/docs/spicedb/ops/observability#opentelemetry-tracing) walks you through sending trace data to a Jaeger endpoint.
270
273
271
-
####Use Partials + Composable Schema to Organize your Schema
274
+
### Use Partials + Composable Schema to Organize your Schema
272
275
273
276
Tags: **schema**
274
277
275
278
As a schema grows in size and complexity, it can become difficult to navigate and grok.
276
279
We implemented [Composable Schemas](https://authzed.com/docs/spicedb/modeling/composable-schemas) to solve this problem, allowing you to break down a schema into multiple files and definitions into multiple problems.
277
280
278
-
####When In Doubt, Add Another Permission
281
+
### When In Doubt, Add Another Permission
279
282
280
283
Tags: **schema**
281
284
282
285
When adding a new feature or service, it can be tempting to re-use existing permissions that currently match the semantics you’re looking for, rather than doing the work of modifying the schema to introduce a new permission.
283
286
However, if the authorization business logic changes between use cases, you’ll not only have to do the work of modifying the permission, but also modifying the call site, so we recommend frontloading that work.
0 commit comments