Added
- New metric
check_permissionship_totalfor CheckPermission and CheckBulkPermissions that counts the number of requests that returned HAS_PERMISSION. Also,write_relationships_updatesalso includes BulkImport calls (#3240)
Changed
- Schema: reads inside write transactions now use a cheap hash-only lookup (
schema_revision) to check the cache before loading the full schema blob, reducing DB round-trips on cache hits (#3160) - Updated the Prometheus buckets for
grpc_server_handling_secondsandspicedb_datastore_query_latencyto be able to correlate them (#3188) - Use
testcontainersinstead ofory/dockertestfor running containers in integration tests (#2782) - Embedded: add
pkg/embedded, an in-process library for running permission checks against a datastore via the dispatch engine, without standing up a gRPC server (#3166) - Caveats: compiled caveats (and their CEL environments) are now cached per schema version — hung off the stored schema (
ReadOnlyStoredSchema) and rebuilt only when the schema changes — rather than rebuilt on every check, reducing check cost for schemas with many caveats (#3166)
Fixed
- Fixed a nil pointer dereference panic in
CheckBulkPermissionsthat could occur under concurrent load when a tracing-enabled check shared a singleflight dispatch with a non-tracing bulk check. Debug-enabled checks are no longer singleflighted together with non-debug checks. (#3174) - Fixed a nil pointer dereference panic in the Postgres FDW (#3235)
- CockroachDB: deletes performed by CockroachDB's row-level TTL job for expired relationships are no longer emitted as
DELETEevents by the Watch API. On CockroachDB ≥ 24.1, SpiceDB sets thettl_disable_changefeed_replicationstorage parameter on the relationship tables at startup (if it lacksALTER TABLEprivileges, it logs a warning with the statement to run manually); on older versions a startup warning is logged and TTL deletes continue to be emitted. Note that the parameter affects any changefeed over these tables — external changefeeds that want TTL deletes can opt back in withignore_disable_changefeed_replication. Delete-only transactions also no longer write an internal transaction-metadata marker row, reducing write amplification. (#3210) - When SpiceDB loses a connection to a CockroachDB node, every read happening in the server blocks for a short period of time (#3181)
- LSP: hover and go-to-definition now resolve identifiers on the right-hand side of arrow expressions (
->,.any(...),.all(...)) (#3157) - The
in_cidrcaveat now matches IPv4-mapped IPv6 addresses (e.g.::ffff:10.1.2.3) against IPv4 CIDRs, the same as the dotted form (#3184) - MySQL: MySQL deadlocks on
WriteRelationships(#3187) - Datastore: a hung datastore round-trip while computing the optimized revision can no longer wedge the server. The revision is computed under singleflight, which detaches the work from the caller's context (stripping its gRPC deadline); a stuck computation (e.g. a half-open connection silently dropped by a load balancer) therefore pinned the latency of every concurrent caller and inflated whole-system P99. The shared computation is now aggressively bounded (2s), with a direct, deadline-respecting retry outside singleflight on failure so a transient wedge does not fail the request. Applies to all datastores. (#3142)
- Postgres & CockroachDB: pooled connections that have gone idle are now liveness-pinged with a bounded timeout (default 5s) before being handed to a query, so a half-open connection is discarded and replaced instead of hanging the acquiring request. (#3142)
- Memory: If SpiceDB couldn't determine the memory available to it (such as can happen in AWS ECS), it assumed that its memory was unbounded. We changed how memory detection works to make conservative estimates in these cases and made some improvements to cache entry cost estimation. (#3201, #3247)
- Datastore: raw datastore driver errors that could leak engine internals (such as SQLSTATE codes or opaque
COPYwrappers) are no longer returned to clients. Unhandled Postgres, MySQL, and CockroachDB driver errors — including CockroachDB's transient retryable/resettable errors — are now surfaced as descriptive, engine-agnostic gRPC statuses (with the full error logged server-side), and an aborted bulk-importCOPYnow reports the underlying source error instead of the driver's opaque wrapper. (#3202)
What's Changed
- release/1.54 by @miparnisari in #3188
- test(lsp): cover arrow RHS multi-match permission branch by @ivanauth in #3182
- fix: match IPv4-mapped IPv6 addresses in the in_cidr caveat by @kanywst in #3184
- fix(mysql): exponential backoff on write retries (#3172) by @ivanauth in #3187
- chore: update buckets for latency and datastore latency by @miparnisari in #3191
- fix(datastore): prevent optimized revision singleflight from wedging the server by @josephschorr in #3142
- test: consolidate TestConsistency by @miparnisari in #3185
- chore: add IsSubset to mapz/ by @miparnisari in #3197
- chore: change how memory limit is set by @tstirrat15 in #3201
- fix(datastore): return descriptive, engine-agnostic errors instead of raw driver errors by @josephschorr in #3202
- ci: stop E2E required check from getting stuck on non-code PRs by @miparnisari in #3205
- chore: Add threat model to SECURITY.md by @jzelinskie in #3194
- chore: update grafana dashboard for CRDB tx restarts, and update gith… by @miparnisari in #3204
- fix: guard nil debug request in bulk check by @ivanauth in #3174
- chore(deps): bump the docker group across 1 directory with 2 updates by @dependabot[bot] in #3178
- fix(crdb): suppress row-level TTL deletes from the Watch API at the source by @josephschorr in #3210
- chore(deps): bump the github-actions group across 1 directory with 12 updates by @dependabot[bot] in #3209
- test: fix flaky TestConsistencyPerDatastore/postgres by @miparnisari in #3216
- chore: replace ory/dockertest with testcontainers by @miparnisari in #2782
- test: fix flaky TestOldWatchingCacheBasicOperation by @miparnisari in #3217
- ci: update benchmark mage targets by @miparnisari in #3221
- chore: fix broken test by @tstirrat15 in #3233
- perf(mysql): force per-query-shape indexes for relationship queries by @josephschorr in #3173
- chore: small followups to the testcontainers PR by @tstirrat15 in #3230
- fix(fdw): prevent nil pointer panic on non-string literals in WHERE c… by @capybara-alt in #3235
- docs(fdw): correct relationships table caveat columns by @capybara-alt in #3229
- chore(deps): bump the docker group with 2 updates by @dependabot[bot] in #3231
- chore: update docker-composes's prometheus version by @miparnisari in #3242
- feat: in-process embedded permissions and per-schema-version caching by @josephschorr in #3166
- feat: add metric counting % of HAS_PERMISSION results by @miparnisari in #3240
- chore(deps): bump google.golang.org/grpc to v1.82.1 by @mazdakb in #3246
- test: add test for catching cache memory leaks by @miparnisari in #3247
New Contributors
- @kanywst made their first contribution in #3184
- @capybara-alt made their first contribution in #3235
Full Changelog: v1.54.0...v1.56.0
Docker Images
This release is available at authzed/spicedb:v1.56.0, quay.io/authzed/spicedb:v1.56.0, ghcr.io/authzed/spicedb:v1.56.0