SQL Server Enterprise Guide
Azure AD, Always On, TDE, and compliance patterns. Enterprise Guide
Teams evaluating GraphQL on SQL Server frequently hit the same wall with Hasura: SQL Server is not a supported data source. FraiseQL is designed from the ground up to treat SQL Server as a first-class target — the same features that work on PostgreSQL work on SQL Server, with no separate product tier or connector required.
| Hasura | FraiseQL | |
|---|---|---|
| SQL Server support | ❌ Not supported | ✅ First-class |
| T-SQL generation | ❌ | ✅ Native, compiled |
| Windows Authentication | ❌ | ✅ Integrated Security |
| Azure AD / Entra ID | ❌ | ✅ ActiveDirectoryMsi |
| Azure SQL Managed Instance | ❌ | ✅ |
| Always On Availability Groups | ❌ | ✅ via AG listener |
| Relay cursor pagination | ❌ (SQL Server) | ✅ v2.0.2+ |
| Row-level security | ❌ (SQL Server) | ✅ via inject + SQL Server RLS |
| Pricing | $995+/month (Hasura Cloud) | Self-hosted, open core |
| Architecture | Runtime SQL generation | Compiled at build time |
Hasura’s architecture was built for PostgreSQL. Its SQL generation, event triggers, and permission system are PostgreSQL-native. SQL Server teams using Hasura either migrate their database to PostgreSQL (costly, risky) or accept a degraded experience through third-party connectors.
FraiseQL’s architecture is database-agnostic at the core. The schema compiler generates database-appropriate SQL — T-SQL for SQL Server, PL/pgSQL for PostgreSQL. Your existing SQL Server infrastructure — stored procedures, indexed views, Row-Level Security policies, Windows Authentication — all work without modification.
[database]url = "server=SQLSERVER01;database=fraiseql_db;integratedSecurity=true;trustServerCertificate=true"Works with Active Directory service accounts. No password stored in config.
[database]url = "server=fraiseql-sql.database.windows.net;database=fraiseql_db;Authentication=ActiveDirectoryMsi"Zero-credential deployment via Managed Identity. No password in any config file or environment variable.
Hasura does not support SQL Server as a data source. Teams running SQL Server with Hasura must either use a PostgreSQL migration or accept limited DDN connector support.
# Offset pagination — available todayquery { posts(limit: 20, offset: 40) { id title }}
# Relay cursor pagination — available in v2.0.2+query { postsConnection(first: 20, after: "cursor...") { edges { node { id title } cursor } pageInfo { hasNextPage endCursor } }}Not available. Hasura does not support SQL Server as a native data source.
FraiseQL’s inject parameter sets SESSION_CONTEXT from JWT claims, enabling SQL Server’s
native RLS policies to filter rows automatically:
-- SQL Server RLS policyCREATE FUNCTION rls.fn_user_filter(@user_id NVARCHAR(36))RETURNS TABLE WITH SCHEMABINDING ASRETURN SELECT 1 AS resultWHERE JSON_VALUE(data, '$.user_id') = @user_id;
CREATE SECURITY POLICY UserFilter ADD FILTER PREDICATE rls.fn_user_filter( CAST(SESSION_CONTEXT(N'user_id') AS NVARCHAR(36)) ) ON dbo.v_documents;FraiseQL sets SESSION_CONTEXT(N'user_id') automatically from the JWT sub claim when you
declare inject = "user_id" on a query. No application code required.
If your team evaluated Hasura and hit the SQL Server limitation, migration to FraiseQL is straightforward because you already have a SQL Server schema.
Install FraiseQL
curl -fsSL https://install.fraiseql.dev | shfraiseql --versionCreate your FraiseQL schema from existing tables
For each table your Hasura evaluation tracked (or would have tracked), create a SQL view and a FraiseQL type. The view selects from your existing tables — no schema changes needed:
-- Create view over your existing tableCREATE VIEW v_post ASSELECT p.id, JSON_QUERY( (SELECT CAST(p.id AS NVARCHAR(36)) AS id, p.title, p.body, CAST(p.user_id AS NVARCHAR(36)) AS userId, FORMAT(p.created_at, 'yyyy-MM-ddTHH:mm:ssZ') AS createdAt FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) ) AS dataFROM posts p;import fraiseql
@fraiseql.typeclass Post: id: str title: str body: str user_id: str created_at: str
@fraiseql.querydef posts(limit: int = 20) -> list[Post]: return fraiseql.config(sql_source="v_post")Map Hasura concepts to FraiseQL equivalents
| Hasura concept | FraiseQL equivalent |
|---|---|
| Track table | SQL view (v_*) |
| Object/array relationships | Nested JSON in view SELECT |
| Permissions (YAML) | SQL Server RLS + FraiseQL inject |
| Actions (HTTP webhook) | Mutations via stored procedures |
| Event triggers | Observers (@observer decorator) |
| Computed fields | Expressions in view SELECT |
| Remote schemas | Federation |
Configure FraiseQL
[project]name = "my-api"
[database]url = "${DATABASE_URL}" # your SQL Server connection string
[server]port = 8080Run
fraiseql runFraiseQL generates SQL views at compile time. At query time, it executes a single indexed view lookup — no per-request SQL generation:
-- FraiseQL: single view query (generated at build time)SELECT data FROM v_post WHERE JSON_VALUE(data, '$.user_id') = @user_id;Hasura’s approach (for databases it supports) generates SQL per request based on the GraphQL query shape. This is flexible but adds latency and makes query plans unpredictable under load.
For SQL Server specifically, pre-built indexed views perform significantly better than dynamically assembled queries because SQL Server can cache execution plans for the view query shape.
Hasura is a better choice when:
FraiseQL on SQL Server is a better choice when:
SQL Server Enterprise Guide
Azure AD, Always On, TDE, and compliance patterns. Enterprise Guide
SQL Server Setup
Connection strings, pool config, and SQL Server-specific patterns. SQL Server Guide
Migrate from Hasura
Full step-by-step migration guide for teams coming from Hasura. Migration Guide
Azure Deployment
Deploy FraiseQL with Azure SQL using Managed Identity. Azure Guide