symion5464
07/14/2026, 7:28 PMresource to be
definition resource {
relation reader: user#member | access_token | role#member | service_account#member
relation writer: user#member | access_token | role#member | service_account#member
relation manager: user#member | access_token | role#member | service_account#member
--- CHANGE ---
permission manage = manager
permission write = writer + manager
permission read = reader + writer + manager
}symion5464
07/14/2026, 7:29 PM-[ RECORD 1 ]---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
query | SELECT * FROM (SELECT object_id, userset_namespace, userset_object_id, userset_relation FROM relation_tuple WHERE pg_visible_in_snapshot(created_xid, $1 ) = $2 AND pg_visible_in_snapshot(deleted_xid, $3 ) = $4 AND namespace = $5 AND relation = $6 AND object_id IN ( $7 , $8 , $9 , $10 , $11 , $12 ) AND ((userset_relation <> $13 ))) AS results WHERE pg_xact_status($14::text::xid8) != $15
calls | 412446
rows | 9293897951
total_time | 13122517.57
mean_time | 31.82
max_time | 3899.52
percentage | 10.01Joey
07/14/2026, 8:05 PMrows | 9293897951Joey
07/14/2026, 8:05 PMsymion5464
07/14/2026, 8:09 PMsymion5464
07/14/2026, 8:09 PMtable_name | estimated_rows
----------------------------+----------------
relation_tuple | 132640symion5464
07/14/2026, 8:09 PMsymion5464
07/14/2026, 8:12 PMsymion5464
07/14/2026, 8:13 PMJoey
07/14/2026, 8:13 PMJoey
07/14/2026, 8:13 PMsymion5464
07/14/2026, 8:13 PMJoey
07/14/2026, 8:13 PMsymion5464
07/14/2026, 8:13 PMJoey
07/14/2026, 8:14 PMJoey
07/14/2026, 8:14 PMsymion5464
07/14/2026, 8:15 PMschema_name | table_name | seq_scan | seq_tup_read | idx_scan | avg_rows
-------------+----------------------------+----------+--------------+-----------+----------
public | relation_tuple | 1685295 | 212090742193 | 247449504 | 125847
public | relation_tuple_transaction | 3738654 | 635035637 | 5588748 | 169
public | namespace_config | 13937378 | 63508279 | 0 | 4
public | schema_revision | 773746 | 773746 | 0 | 1
public | alembic_version | 286571 | 286571 | | 1
public | metadata | 273190 | 273190 | 0 | 1Joey
07/14/2026, 8:23 PMVACUUM FULL ANALYZE to fully analyze and vacuum but it WILL LOCK YOUR DBsymion5464
07/14/2026, 8:26 PMsymion5464
07/14/2026, 8:27 PMsymion5464
07/14/2026, 8:52 PMfalse
a true comes back pretty quick.Joey
07/14/2026, 8:54 PMJoey
07/14/2026, 8:54 PMJoey
07/14/2026, 8:55 PMSELECT * FROM (SELECT object_id, userset_namespace, userset_object_id, userset_relation FROM relation_tuple WHERE pg_visible_in_snapshot(created_xid, $1 ) = $2 AND pg_visible_in_snapshot(deleted_xid, $3 ) = $4 AND namespace = $5 AND relation = $6 AND object_id IN ( $7 , $8 , $9 , $10 , $11 , $12 ) AND ((userset_relation <> $13 ))) AS results WHERE pg_xact_status($14::text::xid8) != $15 should be multiple seconds unless it is (a) returning an insane amount of data or (b) its using the wrong indexJoey
07/14/2026, 8:55 PMJoey
07/14/2026, 8:55 PMsymion5464
07/14/2026, 9:16 PMJoey
07/14/2026, 9:19 PMsymion5464
07/14/2026, 9:24 PMresource definition in our schema is kind of generic where we are granting r/w access to classes of things (resources). not object level access. So those are reused a lot. we use roles to groupl those together. and all of our users get 1 of like 4 default roles.
so i think yes. roles are shared quite a lotsymion5464
07/14/2026, 9:25 PM13489 times in the relation_tuple tablesymion5464
07/14/2026, 9:28 PMsymion5464
07/14/2026, 9:30 PMselect namespace, object_id, count(*) as total from relation_tuple group by namespace, object_id order by total DESC;
namespace | object_id | total
-----------------+---------------------------------------------------+-------
role | 68e69c3237365e926746ca74 | 59136
role | 64e4e46429090ea954d7981a | 45564
role | 64e4e46429090ea954d7981d | 21242
role | 64e4e46429090ea954d79817 | 2318
resource | owner | 1452
resource | pipeline | 52
resource | role | 42
<SNIP>Joey
07/14/2026, 9:41 PMJoey
07/14/2026, 9:41 PMsymion5464
07/14/2026, 9:43 PMdefinition user {
relation inheritor: access_token
permission member = inheritor
}
definition role {
relation inheritor: user#member | access_token | service_account#member
relation parent_role: role#member
permission member = inheritor + parent_role
permission parent = parent_role
}Joey
07/14/2026, 9:43 PMaccess_token?symion5464
07/14/2026, 9:45 PMJoey
07/14/2026, 10:27 PMJoey
07/14/2026, 10:27 PMsymion5464
07/14/2026, 10:29 PMsymion5464
07/14/2026, 10:30 PMsymion5464
07/14/2026, 10:33 PMsymion5464
07/14/2026, 10:35 PMJoey
07/14/2026, 10:35 PMJoey
07/14/2026, 10:35 PMsymion5464
07/14/2026, 10:36 PMsymion5464
07/14/2026, 10:37 PMJoey
07/14/2026, 10:39 PMJoey
07/14/2026, 10:39 PMsymion5464
07/14/2026, 10:39 PMsymion5464
07/14/2026, 10:45 PMsymion5464
07/14/2026, 10:53 PMJoey
07/14/2026, 11:08 PMJoey
07/14/2026, 11:08 PMsymion5464
07/14/2026, 11:16 PMJoey
07/14/2026, 11:27 PMJoey
07/14/2026, 11:27 PMJoey
07/14/2026, 11:28 PMJoey
07/14/2026, 11:28 PMrelation inheritor: user#member was instead relation inheritor: userJoey
07/14/2026, 11:28 PMJoey
07/14/2026, 11:28 PMJoey
07/14/2026, 11:28 PMsymion5464
07/14/2026, 11:38 PMJoey
07/14/2026, 11:39 PMsymion5464
07/14/2026, 11:43 PMJoey
07/14/2026, 11:47 PMJoey
07/14/2026, 11:47 PMsymion5464
07/14/2026, 11:52 PMJoey
07/14/2026, 11:56 PMsymion5464
07/15/2026, 12:18 AMsymion5464
07/15/2026, 12:31 AMsymion5464
07/15/2026, 3:14 AMdefinition user {}
definition service_account {}
definition access_token {
relation user_owner: user
relation service_owner: service_account
}
definition role {
// Roles allow users, service accounts, and other roles to be members
relation member: user | service_account | access_token | role#member | access_token#user_owner | access_token#service_owner
// Computes the inheritance down the tree
permission assigned_member = member
}
definition resource {
relation manager: user | service_account | access_token | role#member
relation writer: user | service_account | access_token | role#member
relation reader: user | service_account | access_token | role#member
permission manage = manager
permission write = writer + manage
permission read = reader + write
}symion5464
07/15/2026, 12:07 PMmember being a comple permission (inheritor + parent_role) rather than a relation is kind of the death of me. But I could be way off. The relationship traversal bit is a bit black box to meJoey
07/15/2026, 6:06 PMsymion5464
07/15/2026, 7:11 PMsymion5464
07/15/2026, 7:11 PMsymion5464
07/15/2026, 7:12 PMsymion5464
07/15/2026, 7:25 PMsymion5464
07/15/2026, 7:28 PMJoey
07/15/2026, 8:38 PMsymion5464
07/15/2026, 8:59 PMuser#member branch here seem like it'll remove the need to walk through all the users?
or does having role#member on the resources necessitate the same thing effectively?symion5464
07/15/2026, 8:59 PMsymion5464
07/15/2026, 9:06 PMrelation writer: user | service_account | access_token | role#member
this bit basically. does including role#member mean that it will have to walk through all roles, and through all users that are a member of the role. because role.member = member: user | service_account | access_token | role#member
is better? or just a different way of creating the same problem?Joey
07/15/2026, 10:23 PMwritersymion5464
07/30/2026, 12:46 AMsymion5464
07/30/2026, 12:48 AMsymion5464
07/30/2026, 12:50 AMdefinition role {
relation parent_role: role#member
relation inheritor_user: user
relation inheritor_token: access_token
relation inheritor_service_account: service_account
permission member_user = inheritor_user + parent_role->member_user
permission member_token = inheritor_token + parent_role->member_token
permission member_service_account = inheritor_service_account + parent_role->member_service_account
}symion5464
07/30/2026, 12:50 AMdefinition resource {
relation reader_user: user
relation reader_token: access_token
relation reader_role: role
relation reader_service_account: service_account
relation writer_user: user
relation writer_token: access_token
relation writer_role: role
relation writer_service_account: service_account
relation manager_user: user
relation manager_token: access_token
relation manager_role: role
relation manager_service_account: service_account
permission manage_user = manager_user + manager_role->member_user
permission manage_token = manager_token + manager_role->member_token
permission manage_service_account = manager_service_account + manager_role->member_service_account
permission write_user = writer_user + writer_role->member_user + manage_user
permission write_token = writer_token + writer_role->member_token + manage_token
permission write_service_account = writer_service_account + writer_role->member_service_account + manage_service_account
permission read_user = reader_user + reader_role->member_user + write_user
permission read_token = reader_token + reader_role->member_token + write_token
permission read_service_account = reader_service_account + reader_role->member_service_account + write_service_account
}symion5464
07/30/2026, 12:51 AMJoey
07/30/2026, 1:27 AMJoey
07/30/2026, 1:27 AM