SpiceDB Documentation
Managing Data
Writing Relationships

Writing relationships

This page will provide some practical recommendations for writing relationships to SpiceDB. If you are interested in relationships as a concept, check out this page.

Retries

When making requests to SpiceDB, it's important to implement proper retry logic to handle transient failures. SpiceDB APIs use gRPC*, which can experience various types of temporary failures that can be resolved through retries.

Retries are recommended for all gRPC methods, not just WriteRelationships.

*SpiceDB can also expose an HTTP API; however, gRPC is recommended.

Implementing Retry Policies

You can implement your own retry policies using the gRPC Service Config. Below, you will find a recommended Retry Policy.

"retryPolicy": {
  "maxAttempts": 3,
  "initialBackoff": "1s",
  "maxBackoff": "4s",
  "backoffMultiplier": 2,
  "retryableStatusCodes": [
    'UNAVAILABLE', 'RESOURCE_EXHAUSTED', 'DEADLINE_EXCEEDED', 'ABORTED',
  ]
}

This retry policy configuration provides exponential backoff with the following behavior:

maxAttempts: 3 - Allows for a maximum of 3 total attempts (1 initial request + 2 retries). This prevents infinite retry loops while giving sufficient opportunity for transient issues to resolve.

initialBackoff: "1s" - Sets the initial delay to 1 second before the first retry attempt. This gives the system time to recover from temporary issues.

maxBackoff: "4s" - Caps the maximum delay between retries at 4 seconds to prevent excessively long waits that could impact user experience.

backoffMultiplier: 2 - Doubles the backoff time with each retry attempt. Combined with the other settings, this creates a retry pattern of: 1s → 2s → 4s.

retryableStatusCodes - Only retries on specific gRPC status codes that indicate transient failures: -UNAVAILABLE: SpiceDB is temporarily unavailable -RESOURCE_EXHAUSTED: SpiceDB is overloaded -DEADLINE_EXCEEDED: Request timed out -ABORTED: Operation was aborted, often due to conflicts that may resolve on retry

You can find a python retry example here (opens in a new tab).

Writes: Touch vs Create

A SpiceDB relationship update (opens in a new tab) can use one of three operation types CREATE, TOUCH, OR DELETE. This section will cover CREATE and TOUCH. You can read more about DELETE in the section below.

Understanding the Operations

CREATE - Inserts a new relationship. If the relationship already exists, the operation will fail with an error.

TOUCH - Upserts a relationship. If the relationship already exists, it will do nothing. If it doesn't exist, it will create it.

Key Differences

OperationBehavior on Existing RelationshipPerformanceUse Case
CREATEFails with errorFaster (single insert)Initial relationship creation
TOUCHUpdates/overwritesSlower (delete + insert)Idempotent operations

Special Considerations

Expiring Relationships: When working with expiring relationships, always use TOUCH. If a relationship has expired but hasn't been garbage collected yet, using CREATE will return an error.

Error Handling: When using CREATE, be prepared to handle duplicate relationship errors appropriately in your application logic.

Deleting Relationships

SpiceDB provides two methods for deleting relationships: using the WriteRelationships API with the DELETE operation or using the DeleteRelationships API. Each approach has different behaviors and use cases.

WriteRelationships with the DELETE Operation

The WriteRelationships (opens in a new tab) API supports a DELETE operation type that allows you to remove specific relationships as part of a batch of relationship updates.

DELETE - Removes a relationship. If the relationship does not exist, the operation will silently succeed (no-op).

Characteristics

  • Atomic Operations: Can be combined with other relationship operations (CREATE, TOUCH) in a single atomic transaction
  • Granular Control: Delete specific relationships alongside creating or updating others
  • Silent Failure: Does not fail if the relationship doesn't exist
  • Batch Limit: Subject to the same batch size limits as other WriteRelationships operations (1,000 updates by default)

DeleteRelationships API

The DeleteRelationships (opens in a new tab) API is a dedicated method for bulk deletion of relationships based on filters rather than specifying individual relationships.

Characteristics

  • Filter-Based: Delete relationships based on resource type, relation, subject type, or combinations thereof
  • Bulk Operations: Can delete many relationships matching the filter criteria in a single call
  • Separate Transaction: Operates independently from WriteRelationships
  • Efficient for Mass Deletion: Optimized for removing large numbers of relationships

Bulk Import

Check out Bulk Importing Relationships

© 2025 AuthZed.