Skip to main content

Strict mode for Ory Permissions

What is strict mode?

Strict mode makes the Ory Permissions engine treat your OPL as the single source of truth during every check. Without strict mode, the engine doesn't use your OPL declarations to filter which tuples it follows — it may follow subject-set pointers that your OPL doesn't specify.

Strict mode is disabled by default. Enable it in the Ory Console under Permissions > Configuration.

Why enable strict mode?

Strict mode improves both performance and correctness:

  • Fewer queries. Ory Keto skips evaluation steps that are impossible given your schema — following undeclared subject-set pointer types, and direct tuple checks on permits rules.
  • No stale grants. Tuples that reference relations removed from your OPL no longer grant access.
  • Explicit errors when limits are reached. Ory Permissions enforces depth and width limits to prevent unbounded graph traversal. In non-strict mode, hitting a limit silently returns { "allowed": false } — identical to a legitimate denial. In strict mode, the engine returns an explicit error so you can tell the check was cut short.
ScenarioNon-strictStrict
Limit hit during single check{ "allowed": false }422 Unprocessable Entity with reason
Limit hit during batch check{ "allowed": false }{ "allowed": false, "error": "max depth reached" }

Ory Network enforces fixed depth and width limits that cannot be changed in the console. If you hit a limit, contact Ory support to discuss your use case.

Known breaking patterns

These patterns work in non-strict mode but break after enabling strict mode.

Subject-set tuples for undeclared types

This covers any tuple that points to a subject-set type your OPL doesn't declare for that relation.

Example: viewers is declared as User[], but a tuple pointing to a Group subject-set was written:

class File implements Namespace {
related: {
viewers: User[] // only Users allowed
}
}

Writing a tuple like this — which assigns a Group subject-set to the viewers relation — will be ignored in strict mode:

keto relation-tuple create Group:engineering#members viewers File:readme

Declare the type in OPL to keep it working:

viewers: (User | SubjectSet<Group, "members">)[]

The same applies in reverse: if viewers is declared as SubjectSet<Group, "members">[] but a direct user tuple was written:

File:readme#viewers@User:alice

Strict mode ignores it because User is not a declared type for that relation.

Tuples written directly against permit relations

Example: canView is a computed permit, but a tuple was written against it directly:

class File implements Namespace {
related: {
editors: User[]
viewers: User[]
}
permits = {
canView: (ctx: Context) => this.related.editors.includes(ctx.subject) || this.related.viewers.includes(ctx.subject),
}
}
File:readme#canView@User:alice

Strict mode skips direct tuple checks on permits rules. Write tuples against editors or viewers instead.

Stale tuples from a renamed or removed relation

If you renamed or removed a relation in OPL but didn't clean up the old tuples, in rare setups, Ory Keto in non-strict mode still follows them. Strict mode ignores them immediately.

How to check if you're ready

Audit two things before enabling:

  1. Tuple writes — every relation you write tuples against should exist in your OPL, and the subject type should match what the relation declares. For example, if your application writes:

    Document:readme#editors@User:alice

    check that the Document namespace in your OPL declares an editors relation, and that it accepts User as a subject type:

    class Document implements Namespace {
    related: {
    editors: User[]
    }
    }
  2. Check requests — every relation you check should be defined in your OPL. For example, if your application calls:

    is User:alice allowed to editors on Document:readme

    verify that editors is declared in the Document namespace.

If both are consistent with your OPL, enabling strict mode produces identical results to non-strict mode — with faster permission checks.

See the Ory Permission Language guide.

Enabling and disabling

Go to the Ory Console, select your project, and navigate to Permissions > Configuration. Toggle Strict mode on or off and save. The change takes effect immediately — no restart required, and no data is modified.