Skip to content

ateapi: add --experimental-openfga-cache-ttl - #3009

Open
Shruti Nair (SHRUTI6991) wants to merge 2 commits into
agent-substrate:mainfrom
SHRUTI6991:ateapi_openfga_cache
Open

Shruti Nair (SHRUTI6991) wants to merge 2 commits into
agent-substrate:mainfrom
SHRUTI6991:ateapi_openfga_cache

Conversation

@SHRUTI6991

@SHRUTI6991 Shruti Nair (SHRUTI6991) commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Every OpenFGA Check reads PostgreSQL. atenet-router calls ResumeActor on every request it routes, so a busy actor gets the same can_resume Check many times a second. This adds an experimental flag to cache Checks in ate-api-server so we can measure the effect under suspend/resume load.

--experimental-openfga-cache-ttl turns on OpenFGA's Check query cache and iterator cache with the given TTL. The default, 0, disables both.

  • The query cache hits when the same principal repeats a Check on the same object, such as the router polling an actor.
  • The iterator cache holds tuple list reads, mostly parent lookups. It doesn't cache single-tuple lookups of direct grants.
  • The cache controller stays off. It polls the changelog once per TTL, so it can't apply writes sooner than a short TTL. Changelog rows are stamped with the transaction start time, so it can also miss writes.

Policy writes don't invalidate either cache. Each cached sub-Check gets a fresh TTL, so a grant or revoke can take up to one TTL per level of the relation chain to apply. The longest chains in model.fga have five levels, so the bound is up to about five times the TTL. docs/authorization.md lists this under known limitations.

OpenFGA's cache counters (openfga_check_cache_*, openfga_tuples_cache_*, openfga_cache_item_*) are served on ate-api-server's /metrics, but not pushed over OTLP. Bridging them is a follow-up.

Benchmark numbers will follow.

AI use: AI-assisted (Jetski). I reviewed the diff.

  • Tests pass (TestNewOpenFGAServer_CheckCache needs Docker; not run locally yet)
  • Docs updated

Enable OpenFGA's Check query cache and iterator cache, each with a 1s
TTL, when --experimental-openfga-cache is set. Policy writes don't
invalidate them, so a grant or revoke can take up to 2s to apply.
@SHRUTI6991
Shruti Nair (SHRUTI6991) marked this pull request as ready for review October 20, 2026 21:21
Comment thread cmd/ateapi/main.go Outdated
postgresSchema = pflag.String("postgres-schema", "substrate", "PostgreSQL schema for Substrate tables. This overrides a search_path connection parameter.")
postgresPoolMaxConns = pflag.Int32("postgres-pool-max-conns", 0, "Maximum connections in the shared Substrate and OpenFGA read/write PostgreSQL pool. Does not affect the owner, watch, or readiness probe pools. The DSN or pgx default is used when unset.")
experimentalEnableAuthz = pflag.Bool("experimental-enable-authz", false, "Enforce OpenFGA authorization checks on all registered RPCs (experimental). AccessPolicy RPCs are always checked.")
experimentalOpenFGACache = pflag.Bool("experimental-openfga-cache", false, "Cache OpenFGA Check results and tuple reads in memory for 1s each (experimental). A grant or revoke can take up to 2s to apply.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we expose a knob for setting the TTL?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. A TTL would let you control both the amount of staleness you are willing to tolerate and whether the feature is enabled or not (TTL=0).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Replaced the bool with --experimental-openfga-cache-ttl. 0 disables the cache.

@haiyanmeng haiyanmeng added kind/feature An enhancement / feature request or implementation area/api-machinery labels Oct 20, 2026
Comment thread cmd/ateapi/internal/authz/authz_util.go Outdated
Comment thread cmd/ateapi/internal/authz/authz_util.go Outdated
// also miss writes: changelog rows are stamped with the transaction
// start time, so a long transaction can commit a row older than one
// the controller has already seen.
opts = append(opts,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any otel metric to monitor the cache? (hit ratio, size, etc).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as OTel metrics. OpenFGA registers Prometheus counters for both caches: openfga_check_cache_hit_count and openfga_check_cache_total_count for the query cache, openfga_tuples_cache_hit_count and openfga_tuples_cache_total_count for the iterator cache, and openfga_cache_item_count for size. ate-api-server serves them on :9090/metrics, but doesn't push them over OTLP.

I have an overall issue for metric tracking here: #2990.

Replace --experimental-openfga-cache with
--experimental-openfga-cache-ttl, where 0 disables the cache.

Each cached sub-Check gets a fresh TTL, so staleness grows by up to one
TTL per level of the relation chain. Describe the bound as up to about
five times the TTL, and add a test for the cache.
@SHRUTI6991 Shruti Nair (SHRUTI6991) changed the title ateapi: add --experimental-openfga-cache ateapi: add --experimental-openfga-cache-ttl Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api-machinery kind/feature An enhancement / feature request or implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants