diff --git a/pages/spicedb/concepts/expiring-relationships.mdx b/pages/spicedb/concepts/expiring-relationships.mdx
new file mode 100644
index 0000000..a908d4a
--- /dev/null
+++ b/pages/spicedb/concepts/expiring-relationships.mdx
@@ -0,0 +1,142 @@
+import { Callout } from 'nextra/components';
+import YouTube from 'react-youtube';
+
+# Expiring Relationships
+
+
+ Expiring Relationships is available from SpiceDB 1.40 onwards.
+
+
+
+ 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.
+ When operating your own database, it's key to keep node clocks in sync - we recommend services like [Amazon Time Sync Service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html).
+ You should evaluate the impact of clock drift in your application.
+
+
+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.
+
+## Schema Use
+
+Expiring relationships follow a similar use to caveated subject types.
+The novelty here is that 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.
+
+```zed
+use expiration
+
+definition folder {}
+
+definition resource {
+ relation folder: folder with expiration
+}
+```
+
+## API Use
+
+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 part of the `OptionalExpiresAt` field in the relationship.
+
+```textproto
+WriteRelationshipsRequest {
+ Updates: [
+ RelationshipUpdate{
+ Operation: CREATE
+ Relationship: {
+ Resource: {
+ ObjectType: "resource",
+ ObjectId: "someresource",
+ },
+ Relation: "viewer",
+ Subject: {
+ ObjectType: "user",
+ ObjectId: "sarah",
+ },
+ OptionalExpiresAt: "2022-12-31T23:59:59Z"
+ }
+ }
+ ]
+}
+```
+
+## 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
+the datastore chosen.
+
+- 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.
+
+
+ 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 Expiration With Caveats
+
+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 also add a combination where both are used:
+
+ ```zed
+ caveat ttl(timeout duration, now string, timeout_creation_timestamp string) {
+ timestamp(now) - timestamp(timeout_creation_timestamp) < timeout
+ }
+
+ definition folder {}
+
+ definition resource {
+ relation folder: folder with ttl
+ }
+ ```
+
+ Becomes:
+
+ ```zed
+ use expiration
+
+ caveat ttl(timeout duration, now string, timeout_creation_timestamp string) {
+ timestamp(now) - timestamp(timeout_creation_timestamp) < timeout
+ }
+
+ definition folder {}
+
+ definition resource {
+ relation folder: folder with ttl | folder with expiration | folder with ttl and expiration
+ }
+ ```
+
+3. Migrate all relationships to use both the caveat and the new expiration.
+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
+
+ definition folder {}
+
+ definition resource {
+ relation folder: folder with expiration
+ }
+ ```