diff --git a/pages/spicedb/concepts/expiring-relationships.mdx b/pages/spicedb/concepts/expiring-relationships.mdx
index 1cca06e..f5f2401 100644
--- a/pages/spicedb/concepts/expiring-relationships.mdx
+++ b/pages/spicedb/concepts/expiring-relationships.mdx
@@ -7,6 +7,18 @@ import YouTube from 'react-youtube';
Expiring Relationships is available from SpiceDB 1.40 onwards.
+A common use case is to model relationships that expire after a certain time.
+This is useful for granting temporary access to a resource.
+
+Until now, caveats were the recommended way to support time-bound permissions, but that has some limitations:
+
+- It requires clients to provide the `now` timestamp.
+This is additional complexity for clients.
+- Expired caveats are not automatically garbage collected.
+This can lead to many caveated relationships in the system and increase the costs of loading and evaluating those into the runtime.
+
+SpiceDB supports expiring relationships, which lets users define relationships that expire at a given time.
+
The clock used to determine if a relationship is expired is that of the underlying SpiceDB datastore.
This gets trickier when using distributed databases like CockroachDB or Spanner, where clocks have an uncertainty range.
@@ -14,23 +26,14 @@ import YouTube from 'react-youtube';
You should evaluate the impact of clock drift in your application.
-A common use-case is to model relationships that expire after a certain amount of time.
-This is useful to grant temporary access to a resource.
-
-Until now, caveats was the recommended way to support time-bound permissions, but that has some limitations:
-
-- It requires clients to provide the `now` timestamp.
- This is additional complexity for clients.
-- Expired caveats are not automatically garbage collected.
- This can lead to a large number of caveats in the system and increasing cost for loading those into the runtime and evaluating them.
-
-SpiceDB supports expiring relationships, which lets users define relationships that expire at a given point in time.
-
## Schema Use
Expiring relationships follow a similar use to caveated subject types.
-The novelty here is that, in order to disambiguate between a caveat named `expiration` and the native `expiration` feature,
-users would need to add a `use` clause to the schema definition to enable the feature.
+The novelty here is that users need to enable the feature using the `use` clause.
+This is to disambiguate a caveat named `expiration` from the new expiration feature.
+
+To enable expiration in your schema, add a `use expiration` clause to the top of the file.
+Then the relations subject to expiration are marked using ` with expiration`:
```zed
use expiration
@@ -44,9 +47,9 @@ definition resource {
## API Use
-Expiration of a relationship is [on a per-relationship basis](https://buf.build/authzed/api/docs/63b8911ef2871c56e5048d1f40a8473f98457ca9:authzed.api.v1#authzed.api.v1.Relationship)
+The expiration of a relationship is [on a per-relationship basis](https://buf.build/authzed/api/docs/63b8911ef2871c56e5048d1f40a8473f98457ca9:authzed.api.v1#authzed.api.v1.Relationship)
at write time, using `WriteRelationships` or `BulkImportRelationships` APIs.
-The expiration is denoted as part of the `OptionalExpiresAt` field in the relationship.
+The expiration is denoted with the `OptionalExpiresAt` field in the relationship.
```textproto
WriteRelationshipsRequest {
@@ -72,29 +75,32 @@ WriteRelationshipsRequest {
## Garbage Collection
+As soon as a relationship expires, it will no longer be used in permission checks.
+However, the row is not deleted right then, but rather is subject to garbage collection.
+
Reclaiming expiring relationships is governed by the same mechanism (and flags) as the deletion of the history of
-relationship changes that powers SpiceDB's own MVCC (Multi-Version Concurrency Control), and heavily depends on
+relationship changes that powers SpiceDB's own MVCC (Multi-Version Concurrency Control) and heavily depends on
the datastore chosen.
-- Datastores like Spanner and CockroachDB have built-in support for expiring SQL rows, so Garbage Collection is done by the database itself.
- In both cases, expired relationships will be reclaimed after 24 hours, and that can't be changed without directly manipulating the SQL schema.
+- Datastores like Spanner and CockroachDB have built-in support for expiring SQL rows, so the database does Garbage Collection.
+In both cases, expired relationships will be reclaimed after 24 hours, which can't be changed without directly manipulating the SQL schema.
- Datastores like Postgres and MySQL support it using the same GC job that reclaims old relationship versions, which runs every 5 minutes.
- Unlike Spanner and CockroachDB, you can govern the GC window with the corresponding flags.
- Relationships will be reclaimed after 24 hours by default.
+Unlike Spanner and CockroachDB, you can govern the GC window with the corresponding flags.
+Relationships will be reclaimed after 24 hours by default.
- GC Window should be adjusted based on the needs of the application. How far does you application need to go back in time?
- If this is a common use-case, we recommend drastrically reducing the GC window (e.g. 1h, or 30 minutes).
+ The GC Window should be adjusted according to the application's needs. How far back in time does your application need to go?
+ If this is a common use case, we recommend drastically reducing the GC window (e.g., 1 hour or 30 minutes).
This means SpiceDB will have to evaluate less data when serving authorization checks, which can improve performance
drastically in large-scale deployments.
-## Migrating Off Expirationg With Caveats
+## Migrating Off Of Expiration With Caveats
-If you implemented expiration using caveats, this section describes the process to migrate to the new expiration feature.
+If you implemented expiration using caveats, this section describes migrating to the new expiration feature.
1. Rename your caveat if you had named it `expiration`
-2. Add the new subject type to your relation, and add also a combination where both are used:
+2. Add the new subject type to your relation, and also add a combination where both are used:
```zed
caveat ttl(timeout duration, now string, timeout_creation_timestamp string) {
@@ -125,12 +131,11 @@ If you implemented expiration using caveats, this section describes the process
```
3. Migrate all relationships to use both the caveat and the new expiration.
- This is needed because only one relationship is allowed for a combination of resource/permission/subject.
-4. Validate that the new expiration feature works as expected by not providing the needed context for the evaluation
- of the `ttl` caveat.
-5. Once validated, migrate completely to the new expiration feature by writting all relationships with only expiration
- and without caveat.
-6. Drop the caveat from your schema once migration is completed
+This is needed because only one relationship is allowed for a resource/permission/subject combination.
+4. Validate that the new expiration feature works as expected by not providing the context for evaluating the `ttl` caveat.
+5. Once validated, migrate completely to the new expiration feature by writing all relationships with only expiration
+and without caveat.
+6. Drop the caveat from your schema once the migration is completed
```zed
use expiration