SqlOS
← Back to Blog

WorkOS FGA vs SqlOS SHRBAC

WorkOS FGA and SqlOS both use hierarchical RBAC ideas. The difference is whether resource authorization lives in WorkOS or in your SQL Server database.

WorkOSFGASHRBACB2B SaaSSqlOS

By Ross Slaney

WorkOS FGA is the closest mental-model comparison to SqlOS SHRBAC (scoped hierarchical RBAC).

It is not a pure graph DSL like Auth0 FGA. WorkOS describes FGA as hierarchical, resource-scoped access control that extends its existing RBAC system. Resources are arranged in a hierarchy and permissions flow down that hierarchy. The official docs are worth reading before making this decision: WorkOS FGA overview, resources, and resource discovery.

SqlOS agrees with that mental model. The difference is the data boundary.

Same hierarchy shape, different data boundary

WorkOS FGA is an external authorization API with resource instances registered in WorkOS. SqlOS uses the same hierarchy idea but keeps resource rows local to your database.

1

WorkOS FGA

  • Resource types in dashboard
  • Register resource instances
  • Authorization API checks
2

Shared model

  • Org -> workspace -> project
  • Roles scoped to resources
  • Permissions inherit downward
3

SqlOS

  • Resource table in SQL Server
  • EF query filters for lists
  • FGA dashboard in your app

The short version

QuestionWorkOS FGASqlOS SHRBAC
Resource instancesRegistered through WorkOS APICreated by your app or FGA admin in SQL Server
Resource hierarchyWorkOS-managed hierarchySqlOS resource table in your database
List filteringAuthorization checks and discovery plus app query logicEF predicate with GetAuthorizationFilterAsync
Mental modelRBAC + hierarchyRBAC + hierarchy
Auth couplingAuthKit, SSO, Directory Sync, organization-scoped IdP role assignmentSqlOS AuthServer in the same host
High-volume rowsUsually stay in your DB with parent referencesCan be modeled as resources when list filtering needs it
CostSaaS pricingMIT license plus your infrastructure

The comparison is not "hierarchy vs no hierarchy." Both have hierarchy. The comparison is "external authorization API vs SQL Server-native authorization rows."

What WorkOS FGA gives you

WorkOS FGA keeps the RBAC vocabulary: roles, permissions, assignments. It adds resource types and resource instances so roles can be assigned at a specific level of your product hierarchy.

The WorkOS docs use examples like organization -> workspace -> project. In that model, a workspace admin can inherit permissions over projects inside the workspace. WorkOS also documents sub-50ms p95 access checks, strong consistency for role changes, and integration with AuthKit, SSO, Directory Sync, and organization-scoped IdP role assignment.

That is compelling if you want to outsource both identity and authorization API operations.

Creating a WorkOS FGA resource is an API operation:

curl https://api.workos.com/authorization/resources \
  -X POST \
  -H "Authorization: Bearer $WORKOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resource_type_slug": "project",
    "external_id": "project_02H",
    "organization_id": "org_01HXYZ",
    "parent_resource_type_slug": "workspace",
    "parent_resource_external_id": "workspace_01H",
    "name": "API Backend"
  }'

Then checks go through the Authorization API:

curl https://api.workos.com/authorization/organization_memberships/om_01HXYZ/check \
  -X POST \
  -H "Authorization: Bearer $WORKOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "permission_slug": "project:edit",
    "resource_type_slug": "project",
    "resource_external_id": "project_02H"
  }'

That is a clean, managed boundary.

The sync question

WorkOS is explicit that resources should mirror your application's data. When entities are created, updated, deleted, or reparented in your app, the corresponding WorkOS resources should change too.

That is reasonable for structural resources:

  • workspaces
  • projects
  • repositories
  • environments
  • dashboards

It is less attractive for high-volume rows:

  • documents
  • messages
  • tasks
  • comments
  • individual records in a list view

WorkOS documentation recommends keeping very high-cardinality content in your database with a reference to a parent FGA resource. That avoids syncing millions of leaf records, but it means the authorization decision is often about the parent, while the actual rows still live in your database.

SqlOS takes the opposite default for a SQL Server app. Resources are database rows, so a protected domain row can describe its resource and SqlOSDbContext<TContext> syncs the backing SqlOSFgaResource during the app write:

var projectId = Guid.NewGuid();
var project = new Project
{
    Id = projectId,
    WorkspaceId = workspace.Id,
    WorkspaceResourceId = workspace.ResourceId,
    ResourceId = $"project::{projectId:D}",
    Name = request.Name
};

// Project implements ISqlOSResourceEntity:
// ResourceTypeId => "project"
// ParentResourceId => WorkspaceResourceId
// ResourceName => Name

dbContext.Projects.Add(project);
await dbContext.SaveChangesAsync(cancellationToken);

There is no vendor sync API for the resource instance because the resource instance is already in your database.

List filtering is the practical fork

WorkOS FGA answers checks and provides discovery endpoints. Those are useful for member lists, sharing dialogs, scoped navigation, and point authorization.

SqlOS focuses heavily on EF list filtering:

var filter = await authService
    .GetAuthorizationFilterAsync<Project>(subjectId, "PROJECT_VIEW");

var page = await dbContext.Projects
    .Where(x => x.WorkspaceId == workspaceId)
    .Where(filter)
    .OrderBy(x => x.Name)
    .Take(25)
    .ToListAsync(cancellationToken);

The query stays a SQL query. Product filtering, authorization filtering, sorting, and pagination remain in one execution plan.

If your app has many list pages and those pages are backed by EF Core over SQL Server, this is not a small implementation detail. It determines where your authorization complexity lives.

Dashboard and support workflow

WorkOS gives you a vendor dashboard and APIs. That is useful when your support and IT workflows already live around WorkOS organizations, SSO, and Directory Sync.

SqlOS gives you an in-app dashboard:

SqlOS FGA resources dashboard
SqlOS resources, grants, roles, permissions, and access tests sit beside the AuthServer dashboard in your own app.

That is useful when support needs to debug a customer row in the same environment where the data exists. The operator can inspect the app row, the resource row, the grant, and the access trace without leaving the deployment.

Decision scenarios

Choose WorkOS FGA when:

  • you want AuthKit, SSO, Directory Sync, Admin Portal, and FGA from one SaaS provider
  • your top-level authorization model is organization, workspace, project, and similar structural resources
  • you are comfortable registering resource instances with WorkOS
  • you want documented sub-50ms p95 managed access checks and vendor operations
  • IdP group to organization role mapping matters today

Choose SqlOS when:

  • you are a SQL Server shop building one .NET product
  • you want auth and FGA data colocated with app data
  • EF list filtering is more important than an external Authorization API
  • you do not want to sync every app-created resource to a vendor
  • you want MIT-licensed infrastructure under your deployment boundary

The honest single-app answer

WorkOS FGA and SqlOS SHRBAC are philosophically closer than Auth0 FGA and SqlOS. Both treat hierarchy as first-class. Both avoid role explosion by letting permissions flow down a tree.

The difference is ownership. WorkOS owns the authorization API and resource registry. SqlOS lets your app own the authorization rows.

For many teams, outsourcing that is the point. For a .NET team already committed to SQL Server, colocating it may be the simpler long-term choice.

Next reading: