https://github.com/fraiseql/fraiseql-python
The Explicit GraphQL Framework for the LLM Era Simple patterns. High performance. PostgreSQL at the center..
https://github.com/fraiseql/fraiseql-python
fastapi fraiseql-v1 graphql postgresql python rag
Last synced: 15 days ago
JSON representation
The Explicit GraphQL Framework for the LLM Era Simple patterns. High performance. PostgreSQL at the center..
- Host: GitHub
- URL: https://github.com/fraiseql/fraiseql-python
- Owner: fraiseql
- License: mit
- Created: 2025-08-06T06:48:59.000Z (11 months ago)
- Default Branch: dev
- Last Pushed: 2026-05-19T02:55:59.000Z (about 1 month ago)
- Last Synced: 2026-05-19T04:57:10.824Z (about 1 month ago)
- Topics: fastapi, fraiseql-v1, graphql, postgresql, python, rag
- Language: Python
- Homepage: https://fraiseql.dev
- Size: 76.6 MB
- Stars: 21
- Watchers: 0
- Forks: 1
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: .github/security-ignore-patterns.txt
Awesome Lists containing this project
README
# FraiseQL
[](https://github.com/fraiseql/fraiseql-python/actions/workflows/ci.yml)
[](https://github.com/fraiseql/fraiseql-python/actions/workflows/docs.yml)
[](https://github.com/fraiseql/fraiseql-python/releases/latest)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
**v1.9.17** | **Stable** | **Rust-Powered GraphQL for PostgreSQL**
**Python**: 3.13+ | **PostgreSQL**: 13+
---
## GraphQL for the LLM era. Simple. Powerful. Rust-fast
PostgreSQL returns JSONB. Rust transforms it. Zero Python overhead.
```python
# Complete GraphQL API in 15 lines
import fraiseql
from fraiseql.fastapi import create_fraiseql_app
@fraiseql.type(sql_source="v_user", jsonb_column="data")
class User:
"""A user in the system.
Fields:
id: Unique user identifier
name: User's full name
email: User's email address
"""
id: int
name: str
email: str
@fraiseql.query
async def users(info) -> list[User]:
"""Get all users."""
db = info.context["db"]
return await db.find("v_user")
app = create_fraiseql_app(
database_url="postgresql://localhost/mydb",
types=[User],
queries=[users]
)
```
---
## π FraiseQL Versions
FraiseQL has two versions with overlapping but complementary strengths:
### v1.9.16 (This Repository: `fraiseql-python`)
**Python framework with integrated Rust pipeline**
- β
**Stable, production-ready** (v1.9.16)
- π **Python 3.13+ native** - write schema in Python decorators
- π **Rust pipeline included** - 7-10x faster JSON transformation
- π‘ **FastAPI runtime** - immediate deployment, hot reload, development-friendly
- ποΈ **PostgreSQL-only** - optimized for PostgreSQL expertise
- π **Iterative development** - no build step, rapid feedback loops
**Best for:** Python teams, rapid iteration, existing PostgreSQL codebases, teams that want Rust performance without leaving Python ecosystem
**Repository:** [fraiseql/fraiseql-python](https://github.com/fraiseql/fraiseql-python)
### v2 (Separate Repository: `fraiseql`)
**Compiled Rust engine with polyglot schema authoring**
- π **Beta stage** (v2.0.0-alpha.2) - feature-complete, actively developed
- π§ **16+ language support** - Python, TypeScript, Go, Java, Rust, etc. (same schema authoring experience)
- β‘ **Compile-time optimization** - build-time schema validation, zero-cost abstractions
- π οΈ **CLI compiler** - `fraiseql-cli compile schema.json`
- ποΈ **Multi-database** - PostgreSQL, MySQL, SQLite, SQL Server
- π― **Maximum performance** - no runtime interpretation, fully compiled
**Best for:** Teams with multiple language ecosystems, multi-database requirements, compile-time optimization, polyglot teams
**Repository:** [fraiseql/fraiseql](https://github.com/fraiseql/fraiseql)
### Comparison
| Aspect | v1.9.16 | v2 |
|--------|---------|-----|
| **Schema in Python** | β
Native | β
Supported (1 of 16+ languages) |
| **Rust Performance** | β
Included | β
Full engine in Rust |
| **PostgreSQL Support** | β
Full | β
Full + 3 others |
| **Deployment Model** | Runtime (FastAPI) | Build-time (CLI compile) |
| **Development Experience** | Hot reload, iterative | Compile step, maximum optimization |
| **Status** | β
Stable | π Beta |
| **Best Migration Path** | Native Python β v2 Python | Python β any language |
> **If you're using Python:** Both versions work great! v1 for rapid iteration, v2 for compile-time guarantees and multi-DB future-proofing. Both are actively maintained.
---
## Why FraiseQL?
- β‘ **Rust Pipeline** - 7-10x faster JSON transformation, zero Python overhead
- π **Secure by Design** - Explicit field contracts prevent data leaks
- π€ **AI-Native** - LLMs generate correct code on first try
- π° **Save $5-48K/year** - Eliminate Redis, Sentry, APM tools
- π **GraphQL Cascade** - Automatic cache updates and side effect tracking
- β¨ **Auto-populated mutations** - status, message, errors handled automatically (50-60% less boilerplate)
- π― **Auto-wired query params** - `where`, `orderBy`, `limit`, `offset` added automatically to list queries
- π **Auto-documentation** - Attribute docstrings become GraphQL descriptions automatically
- π **Advanced filtering** - Full-text search, JSONB queries, array operations, regex
- π§ **Vector search** - pgvector integration for semantic search, RAG, recommendations (6 distance operators)
- π **GraphQL compliant** - 85-90% GraphQL spec compliance with advanced fragment support
---
## Is This For You?
**β
Perfect if you:**
- Build high-performance APIs with PostgreSQL
- Want 7-10x faster JSON processing
- Need enterprise security & compliance
- Prefer database-first architecture
- Use LLMs for code generation
**β Consider alternatives if:**
- You need multi-database support (PostgreSQL-only)
- Building your first GraphQL API (use simpler frameworks)
- Don't use JSONB columns in PostgreSQL
---
## How It Works
**Traditional GraphQL** (slow):
```
PostgreSQL β Rows β ORM deserialize β Python objects β GraphQL serialize β JSON β Response
β°βββ Unnecessary roundtrips (2 conversions) ββββ―
```
**FraiseQL** (fast):
```
PostgreSQL β JSONB β Rust field selection β HTTP Response
β°β Zero Python overhead (1 conversion) ββ―
```
### Why This Is Better
1. **No ORM Overhead** - Database returns final JSONB, Rust transforms it
2. **No N+1 Queries** - PostgreSQL composes everything in one query
3. **Security Built-In** - View defines exactly what's exposed (impossible to leak)
4. **Recursion Safe** - View structure prevents depth attacks naturally
5. **AI-Friendly** - SQL + Python are massively trained; no magic frameworks
---
## Quick Start
```bash
pip install fraiseql
fraiseql init my-api
cd my-api
fraiseql dev
```
**Your GraphQL API is live at `http://localhost:8000/graphql`** π
**Next steps:**
- [5-Minute Quickstart](docs/getting-started/quickstart.md)
- [First Hour Guide](docs/getting-started/first-hour.md) - Build a complete blog API
- [Understanding FraiseQL](docs/guides/understanding-fraiseql.md) - Architecture deep-dive
---
## Real Security, Not Theatre
### The Problem (ORM-based frameworks)
```python
class User(Base): # SQLAlchemy
id = Column(Integer)
email = Column(String)
password_hash = Column(String) # β Sensitive!
api_key = Column(String) # β Sensitive!
@strawberry.type
class UserType:
id: int
email: str
# Forgot to exclude password_hash and api_key!
```
**Result:** One mistake = data leak.
### The Solution (FraiseQL)
```sql
-- PostgreSQL view defines what's exposed
CREATE VIEW v_user AS
SELECT id,
jsonb_build_object('id', id, 'email', email) as data
FROM tb_user;
-- password_hash and api_key aren't in JSONB = impossible to leak
```
**Result:** Structure defines the contract. No way to accidentally expose fields.
---
## Chaos Engineering & Resilience Testing
FraiseQL separates testing into two workflows:
| Aspect | Standard CI/CD | Chaos Engineering |
|--------|---|---|
| **Duration** | 15-20 min | 45-60 min |
| **Purpose** | Correctness | Resilience |
| **Trigger** | Every PR | Manual/Weekly |
| **Tests** | Unit + Integration | 71 chaos scenarios |
| **Blocks Merges** | Yes β
| No (informational) |
| **Environment** | Lightweight | Real PostgreSQL + Docker |
**Standard CI/CD:** Validates that features work correctly
**Chaos Tests:** Validates that system recovers from failures
[β Learn about chaos engineering strategy](docs/archive/testing/chaos-engineering-strategy.md)
---
## Advanced Features
### Specialized Type System (50+ scalar types)
```python
from fraiseql.types import EmailAddress, PhoneNumber, IPv4, Money, LTree
@fraiseql.type(sql_source="v_users")
class User:
email: EmailAddress # Validated emails
phone: PhoneNumber # International phone numbers
ip: IPv4 # IP addresses with subnet operations
balance: Money # Currency with precision
location: LTree # Hierarchical paths
```
### Trinity Identifiers
Three ID types for different purposes:
- **pk_user** (int): Internal DB key, not exposed
- **id** (UUID): Public API, stable, never changes
- **identifier** (str): Human-readable slug, SEO-friendly
### GraphQL Cascade
Automatic cache invalidation when mutations change related data:
```graphql
mutation {
createPost(input: {...}) {
post { id title }
cascade {
updated { __typename } # What changed
invalidations { queryName } # Which queries to invalidate
}
}
}
```
---
## Enterprise Security Features
- **KMS Integration:** Vault, AWS KMS, GCP Cloud KMS
- **Security Profiles:** STANDARD, REGULATED, RESTRICTED (government-grade)
- **SBOM Generation:** Automated compliance (FedRAMP, NIS2, HIPAA, PCI-DSS)
- **Audit Logging:** Cryptographic chain (SHA-256 + HMAC)
- **Row-Level Security:** PostgreSQL RLS integration
- **Rate Limiting:** Per-endpoint and per-GraphQL operation
[π Security Configuration](docs/production/security.md)
### π Security Feature Implementation Status
| Feature | Configured | Enforced | Tested | Production Ready | Notes |
|---------|-----------|----------|--------|------------------|-------|
| **Authentication** | β
| β
| β οΈ Partial | β οΈ Use with caution | Rust-based JWT validation via `PyAuthProvider` |
| **RBAC Framework** | β
| β
| β οΈ Framework only | β οΈ Use with caution | Permission resolution complete, enforcement verification tests pending |
| **Security Profiles** | β
| β οΈ Partial | β οΈ Partial | β Not production ready | TLS/rate limiting enforced; query limits/audit pending |
| **Field Filtering (Mutations)** | β
| β
| β
| β
Production ready | Full implementation (v1.9.16+) |
| **Field Filtering (APQ)** | β
| β
| β οΈ Partial | β οΈ Limited scope | APQ queries only |
| **Field Filtering (Queries)** | β οΈ | β οΈ | β οΈ | β οΈ Verification needed | Non-APQ query filtering status unclear |
| **Rate Limiting** | β
| β
| β
| β
Production ready | Per-endpoint and per-operation |
| **CSRF Protection** | β
| β
| β
| β
Production ready | Automatic middleware |
| **Security Headers** | β
| β
| β
| β
Production ready | Defense in depth |
| **Body Size Limits** | β
| β
| β
| β
Production ready | Configurable per profile |
| **TLS Enforcement** | β
| β
| β
| β
Production ready | Profile-based |
| **Query Depth Limits** | β
Config | β Pending | β | β Not ready | Validator middleware needed |
| **Query Complexity** | β
Config | β Pending | β | β Not ready | AST analysis pending |
| **Introspection Policy** | β
Config | β Pending | β | β Not ready | Control logic pending |
| **Audit Logging** | β
Config | β Pending | β | β Not ready | Middleware implementation needed |
**Legend:**
- β
Complete and verified
- β οΈ Partial implementation or limited scope
- β Not implemented or not production ready
**Roadmap:**
- **v1.9.16**: Complete security profile enforcement (Issue #225)
- **v1.9.16**: Add RBAC enforcement verification tests
- **v1.9.16**: Unified field filtering for all query types
- **v1.9.16**: Full security audit and penetration testing
> **Important**: This matrix reflects current implementation status (v1.9.16). Security features are under active development. Always verify features meet your requirements before production deployment. See [Issue #225](https://github.com/fraiseql/fraiseql-python/issues/225) for implementation progress.
---
## Cost Savings: Replace 4 Services with 1 Database
| Service | Cost | FraiseQL Approach | Savings |
|---------|------|------------------|---------|
| Redis (caching) | $50-500/mo | PostgreSQL UNLOGGED tables | $600-6,000/yr |
| Sentry (error tracking) | $300-3,000/mo | PostgreSQL error logging | $3,600-36,000/yr |
| APM Tool | $100-500/mo | PostgreSQL traces | $1,200-6,000/yr |
| **Total** | **$450-4,000/mo** | **PostgreSQL only ($50/mo)** | **$5,400-48,000/yr** |
### π Software Bill of Materials (SBOM)
- **Automated generation** via `fraiseql sbom generate`
- **Global compliance**: US EO 14028, EU NIS2/CRA, PCI-DSS 4.0, ISO 27001
- **CycloneDX 1.5 format** with cryptographic signing
- **CI/CD integration** for continuous compliance
### π Key Management Service (KMS)
- **HashiCorp Vault**: Production-ready with transit engine
- **AWS KMS**: Native integration with GenerateDataKey
- **GCP Cloud KMS**: Envelope encryption support
- **Local Provider**: Development-only with warnings
### π‘οΈ Security Profiles
- `STANDARD`: Default protections for general applications
- `REGULATED`: PCI-DSS/HIPAA/SOC 2 compliance
- `RESTRICTED`: Government, defence, critical infrastructure
- πΊπΈ FedRAMP, DoD, NIST 800-53
- πͺπΊ NIS2 Essential Entities, EU CRA
- π¨π¦ CPCSC (defence contractors)
- π¦πΊ Essential Eight Level 3
- πΈπ¬ Singapore CII operators
### π Observability
- OpenTelemetry tracing with sensitive data sanitization
- Security event logging
- Audit trail support
### π Advanced Security Controls
- **Rate limiting** for API endpoints and GraphQL operations
- **CSRF protection** for mutations and forms
- **Security headers** middleware for defense in depth
- **Input validation** and sanitization
- **Field-level authorization** with role inheritance
- **Row-level security** via PostgreSQL RLS
**[π KMS Architecture](https://github.com/fraiseql/fraiseql-python/blob/main/docs/architecture/decisions/0003-kms-architecture.md)**
---
## Code Examples
### Complete CRUD API
```python
@fraiseql.input
class CreateUserInput:
email: str # AI sees exact input structure
name: str
@fraiseql.success
class UserCreated:
user_id: str # AI sees success response
# Note: @success auto-injects: status, message, updated_fields, id
@fraiseql.error
class ValidationError:
error: str # AI sees failure cases
code: str = "VALIDATION_ERROR"
@fraiseql.mutation(function="fn_create_user", schema="public")
class CreateUser:
input: CreateUserInput
success: UserCreated
failure: ValidationError # Note: Use 'failure' field, not '@failure' decorator
# That's it! FraiseQL automatically:
# 1. Calls public.fn_create_user(input) with input as dict
# 2. Parses JSONB result into UserCreated or ValidationError
```
### Why AI Loves This
- β
**SQL + Python** - Massively trained languages (no proprietary DSLs)
- β
**JSONB everywhere** - Clear data structures, obvious contracts
- β
**Database functions** - Complete context in one file
- β
**Explicit logging** - AI can trace execution without debugging
- β
**No abstraction layers** - What you see is what executes
**Real Impact:** Claude Code, GitHub Copilot, and ChatGPT generate correct FraiseQL code on first try.
---
## π Core Concepts
**New to FraiseQL?** Understanding these core concepts will help you make the most of the framework:
**[π Concepts & Glossary](https://github.com/fraiseql/fraiseql-python/blob/main/docs/core/concepts-glossary.md)** - Essential terminology and mental models:
- **CQRS Pattern** - Separate read models (views) from write models (functions)
- **Trinity Identifiers** - Three-tier ID system (`pk_*`, `id`, `identifier`) for performance and UX
- **JSONB Views** - PostgreSQL composes data once, eliminating N+1 queries
- **Database-First Architecture** - Start with PostgreSQL, GraphQL follows
- **Explicit Sync Pattern** - Table views (`tv_*`) for complex queries
**Quick links:**
- [Understanding FraiseQL](https://github.com/fraiseql/fraiseql-python/blob/main/docs/guides/understanding-fraiseql.md) - 10-minute architecture overview
- [Database API](https://github.com/fraiseql/fraiseql-python/blob/main/docs/core/database-api.md) - Connection pooling and query execution
- [Types and Schema](https://github.com/fraiseql/fraiseql-python/blob/main/docs/core/types-and-schema.md) - Complete type system guide
- [Filter Operators](https://github.com/fraiseql/fraiseql-python/blob/main/docs/advanced/filter-operators.md) - Advanced PostgreSQL filtering (arrays, full-text search, JSONB, regex)
---
## β¨ See How Simple It Is
### Complete CRUD API in 20 Lines
```python
from uuid import UUID
from fraiseql import type, query, mutation, input, success
@fraiseql.type(sql_source="v_note", jsonb_column="data")
class Note:
id: int
title: str
content: str | None
@fraiseql.query
async def notes(info) -> list[Note]:
return await info.context["db"].find("v_note")
@fraiseql.query
async def note(info, id: UUID) -> Note | None:
"""Get a note by ID."""
db = info.context["db"]
return await db.find_one("v_note", id=id)
# Step 3: Define mutations
@fraiseql.input
class CreateNoteInput:
title: str
content: str | None = None
@fraiseql.mutation
class CreateNote:
input: CreateNoteInput
success: Note
app = create_fraiseql_app(
database_url="postgresql://localhost/mydb",
types=[Note],
queries=[notes],
mutations=[CreateNote]
)
```
### Database-First Pattern
```sql
-- PostgreSQL view (composable, no N+1)
CREATE VIEW v_user AS
SELECT id,
jsonb_build_object(
'id', id,
'name', name,
'email', email,
'posts', (
SELECT jsonb_agg(...)
FROM tb_post p
WHERE p.user_id = tb_user.id
)
) as data
FROM tb_user;
```
```python
# Python type mirrors the view
@fraiseql.type(sql_source="v_user", jsonb_column="data")
class User:
id: int
name: str
email: str
posts: list[Post] # Nested relations! No N+1 queries!
# Step 3: Query it
@fraiseql.query
async def users(info) -> list[User]:
db = info.context["db"]
return await db.find("v_user")
```
**No ORM. No complex resolvers. PostgreSQL composes data, Rust transforms it.**
### Mutations with Business Logic
```sql
CREATE OR REPLACE FUNCTION fn_publish_post(p_post_id UUID) RETURNS JSONB AS $$
DECLARE
v_post RECORD;
BEGIN
-- Get post with user info (Trinity pattern: JOIN on pk_user)
SELECT p.*, u.email as user_email
INTO v_post
FROM tb_post p
JOIN tb_user u ON p.fk_user = u.pk_user -- β
Trinity: INTEGER FK to pk_user
WHERE p.id = p_post_id;
-- Validate post exists
IF NOT FOUND THEN
RETURN jsonb_build_object('success', false, 'error', 'Post not found');
END IF;
-- Validate not already published
IF v_post.published_at IS NOT NULL THEN
RETURN jsonb_build_object('success', false, 'error', 'Post already published');
END IF;
-- Update post
UPDATE tb_post
SET published_at = NOW()
WHERE id = p_post_id;
-- Sync projection table
PERFORM fn_sync_tv_post(p_post_id);
-- Log event
INSERT INTO audit_log (action, details)
VALUES ('post_published', jsonb_build_object('post_id', p_post_id, 'user_email', v_post.user_email));
-- Return success
RETURN jsonb_build_object('success', true, 'post_id', p_post_id);
END;
$$ LANGUAGE plpgsql;
```
**Business logic, validation, logging - all in the database function. Crystal clear for humans and AI.**
### Selective CASCADE Querying
Request only the CASCADE data you need:
```graphql
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
post { id title }
# Option 1: No CASCADE (smallest payload)
# Just omit the cascade field
# Option 2: Metadata only
cascade {
metadata { affectedCount }
}
# Option 3: Full CASCADE
cascade {
updated { __typename id entity }
deleted { __typename id }
invalidations { queryName }
metadata { affectedCount }
}
}
}
```
Performance: Not requesting CASCADE reduces response size by 2-10x.
---
## π° In PostgreSQL Everything
Replace 4 services with 1 database.
### Cost Savings Calculator
| Traditional Stack | FraiseQL Stack | Annual Savings |
|-------------------|----------------|----------------|
| PostgreSQL: $50/mo | PostgreSQL: $50/mo | - |
| **Redis Cloud:** $50-500/mo | β
**In PostgreSQL** | **$600-6,000/yr** |
| **Sentry:** $300-3,000/mo | β
**In PostgreSQL** | **$3,600-36,000/yr** |
| **APM Tool:** $100-500/mo | β
**In PostgreSQL** | **$1,200-6,000/yr** |
| **Total: $500-4,050/mo** | **Total: $50/mo** | **$5,400-48,000/yr** |
### How It Works
**Caching (Replaces Redis)**
```python
from fraiseql.caching import PostgresCache
cache = PostgresCache(db_pool)
await cache.set("user:123", user_data, ttl=3600)
# Uses PostgreSQL UNLOGGED tables
# - No WAL overhead = fast writes
# - Shared across instances
# - TTL-based expiration
# - Pattern-based deletion
```
**Error Tracking (Replaces Sentry)**
```python
from fraiseql.monitoring import init_error_tracker
tracker = init_error_tracker(db_pool, environment="production")
await tracker.capture_exception(error, context={...})
# Features:
# - Automatic error fingerprinting and grouping
# - Full stack trace capture
# - OpenTelemetry trace correlation
# - Custom notifications (Email, Slack, Webhook)
```
**Observability (Replaces APM)**
```sql
-- All traces and metrics stored in PostgreSQL
SELECT * FROM monitoring.traces
WHERE error_id = 'error-123'
AND trace_id = 'trace-xyz';
```
**Grafana Dashboards**
Pre-built dashboards in `grafana/` query PostgreSQL directly:
- Error monitoring dashboard
- Performance metrics dashboard
- OpenTelemetry traces dashboard
### Operational Benefits
- β
**70% fewer services** to deploy and monitor
- β
**One database to backup** (not 4 separate systems)
- β
**No Redis connection timeouts** or cluster issues
- β
**No Sentry quota surprises** or rate limiting
- β
**ACID guarantees** for everything (no eventual consistency)
- β
**Self-hosted** - full control, no vendor lock-in
---
## ποΈ Architecture Deep Dive
### Rust-First Execution
```
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β GraphQL β β β PostgreSQL β β β Rust β
β Request β β JSONB Query β β Transform β
β β β β β (7-10x faster)β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β
βββββββββββββββββββ
β FastAPI β
β HTTP Response β
βββββββββββββββββββ
```
**Unified path for all queries:**
1. **GraphQL query** arrives at FastAPI
2. **Python resolver** calls PostgreSQL view/function
3. **PostgreSQL** returns pre-composed JSONB
4. **Rust pipeline** transforms JSONB based on GraphQL selection
5. **FastAPI** returns bytes directly (zero Python serialization)
### CQRS Pattern
FraiseQL implements Command Query Responsibility Segregation:
```
βββββββββββββββββββββββββββββββββββββββ
β GraphQL API β
ββββββββββββββββββββ¬βββββββββββββββββββ€
β QUERIES β MUTATIONS β
β (Reads) β (Writes) β
ββββββββββββββββββββΌβββββββββββββββββββ€
β v_* views β fn_* functions β
β tv_* tables β tb_* tables β
β JSONB ready β Business logic β
ββββββββββββββββββββ΄βββββββββββββββββββ
```
**Queries use views:**
- `v_*` - Real-time views with JSONB computation
- `tv_*` - Denormalized tables with generated JSONB columns (for complex queries)
**Mutations use functions:**
- `fn_*` - Business logic, validation, side effects
- `tb_*` - Base tables for data storage
**[π Detailed Architecture Diagrams](https://github.com/fraiseql/fraiseql-python/blob/main/docs/guides/understanding-fraiseql.md)**
### Key Innovations
**1. Exclusive Rust Pipeline**
- PostgreSQL β Rust β HTTP (no Python JSON processing)
- 7-10x faster JSON transformation vs Python
- No GIL contention, compiled performance
**2. JSONB Views**
- Database composes data once
- Rust selects fields based on GraphQL query
- No N+1 query problems
**3. Table Views (tv_*)**
```sql
-- Denormalized JSONB table with explicit sync
CREATE TABLE tv_user (
id INT PRIMARY KEY,
data JSONB NOT NULL, -- Regular column, not generated
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Sync function populates tv_* from v_* view
CREATE FUNCTION fn_sync_tv_user(p_user_id INT) RETURNS VOID AS $$
BEGIN
INSERT INTO tv_user (id, data)
SELECT id, data FROM v_user WHERE id = p_user_id
ON CONFLICT (id) DO UPDATE SET
data = EXCLUDED.data,
updated_at = NOW();
END;
$$ LANGUAGE plpgsql;
-- Mutations call sync explicitly
CREATE FUNCTION fn_create_user(p_name TEXT) RETURNS JSONB AS $$
DECLARE v_user_id INT;
BEGIN
INSERT INTO tb_user (name) VALUES (p_name) RETURNING id INTO v_user_id;
PERFORM fn_sync_tv_user(v_user_id); -- β Explicit sync call
RETURN (SELECT data FROM tv_user WHERE id = v_user_id);
END;
$$ LANGUAGE plpgsql;
```
Benefits: Instant lookups, embedded relations, explicitly synchronized
**4. Zero-Copy Response**
- Direct RustResponseBytes to FastAPI
- No Python serialization overhead
- Optimal for high-throughput APIs
---
## π― How FraiseQL Is Different
### Execution Path Comparison
| Framework | Data Flow | JSON Processing | Recursion Protection | Security Model |
|-----------|-----------|-----------------|----------------------|----------------|
| **FraiseQL** | PostgreSQL JSONB β Rust β HTTP | β
Rust (compiled) | β
View-enforced | β
Explicit contracts |
| Strawberry + SQLAlchemy | PostgreSQL β ORM β Python dict β JSON | β Python (2 steps) | β οΈ Middleware required | β ORM over-fetching risk |
| Hasura | PostgreSQL β Haskell β JSON | β οΈ Haskell | β οΈ Middleware required | β οΈ Complex permission system |
| PostGraphile | PostgreSQL β Node.js β JSON | β οΈ JavaScript | β οΈ Middleware required | β οΈ Plugin-based |
### FraiseQL's Unique Advantages
- β
**Database returns final structure** (JSONB views)
- β
**Rust handles field selection** (compiled performance)
- β
**No Python in hot path** (zero serialization overhead)
- β
**No ORM abstraction** (SQL functions are business logic)
- β
**Built-in recursion protection** (view defines max depth, no middleware needed)
- β
**Secure by design** (explicit field contracts prevent data leaks)
- β
**AI-readable** (clear contracts, full context visible)
- β
**PostgreSQL-native** (caching, monitoring, APQ in one database)
---
## π― Advanced Features
### Automatic Persisted Queries (APQ)
Enterprise-grade APQ with pluggable storage backends:
```python
from fraiseql import FraiseQLConfig
# Memory backend (zero configuration)
config = FraiseQLConfig(apq_storage_backend="memory")
# PostgreSQL backend (multi-instance coordination)
config = FraiseQLConfig(
apq_storage_backend="postgresql",
apq_storage_schema="apq_cache"
)
```
**How it works:**
1. Client sends query hash instead of full query
2. FraiseQL checks storage backend for cached query
3. PostgreSQL β Rust β HTTP (same fast path)
4. Bandwidth reduction with large queries
**[β‘ APQ Details](https://github.com/fraiseql/fraiseql-python/blob/main/docs/diagrams/apq-cache-flow.md)**
### Specialized Type System
Advanced operators for network types, hierarchical data, ranges, and nested arrays:
```graphql
query {
servers(where: {
ipAddress: { eq: "192.168.1.1" } # β ::inet casting
port: { gt: 1024 } # β ::integer casting
location: { ancestor_of: "US.CA" } # β ltree operations
dateRange: { overlaps: "[2024-01-01,2024-12-31)" }
# Nested array filtering with logical operators
printServers(where: {
AND: [
{ operatingSystem: { in: ["Linux", "Windows"] } }
{ OR: [
{ nTotalAllocations: { gte: 100 } }
{ NOT: { ipAddress: { isnull: true } } }
]
}
]
}) {
hostname operatingSystem
}
}) {
id name ipAddress port
}
}
```
**50+ Specialized Scalar Types:**
**Financial & Trading:**
- CUSIP, ISIN, SEDOL, MIC, LEI - Security identifiers
- Money, Percentage, ExchangeRate - Financial values
- CurrencyCode, StockSymbol - Trading symbols
**Network & Infrastructure:**
- IPv4, IPv6, CIDR, MACAddress - Network addresses with subnet operations
- Hostname, DomainName, Port, EmailAddress - Internet identifiers
- APIKey, HashSHA256 - Security tokens
**Geospatial & Location:**
- Coordinate, Latitude, Longitude - Geographic coordinates with distance calculations
- PostalCode, Timezone - Location data
**Business & Logistics:**
- ContainerNumber, FlightNumber, TrackingNumber, VIN - Asset identifiers
- IBAN, LicensePlate - Financial & vehicle identifiers
- PhoneNumber, LocaleCode, LanguageCode - Contact & localization
**Technical & Data:**
- UUID, JSON, Date, DateTime, Time, DateRange - Standard types with validation
- LTree - Hierarchical data with ancestor/descendant queries
- SemanticVersion, Color, MIMEType, File, Image - Specialized formats
- HTML, Markdown - Rich text content
**Advanced Filtering:** Full-text search, JSONB queries, array operations, regex, vector similarity search on all types
#### Scalar Type Usage Examples
```python
from fraiseql import type
from fraiseql.types import (
EmailAddress, PhoneNumber, Money, Percentage,
CUSIP, ISIN, IPv4, MACAddress, LTree, DateRange
)
@fraiseql.type(sql_source="v_financial_data")
class FinancialRecord:
id: int
email: EmailAddress # Validated email addresses
phone: PhoneNumber # International phone numbers
balance: Money # Currency amounts with precision
margin: Percentage # Percentages (0.00-100.00)
security_id: CUSIP | ISIN # Financial instrument identifiers
@fraiseql.type(sql_source="v_network_device")
class NetworkDevice:
id: int
ip_address: IPv4 # IPv4 addresses with subnet operations
mac_address: MACAddress # MAC addresses with validation
location: LTree # Hierarchical location paths
maintenance_window: DateRange # Date ranges with overlap queries
```
```graphql
# Advanced filtering with specialized types
query {
financialRecords(where: {
balance: { gte: "1000.00" } # Money comparison
margin: { between: ["5.0", "15.0"] } # Percentage range
security_id: { eq: "037833100" } # CUSIP validation
}) {
id balance margin security_id
}
networkDevices(where: {
ip_address: { inSubnet: "192.168.1.0/24" } # CIDR operations
location: { ancestor_of: "US.CA.SF" } # LTree hierarchy
maintenance_window: { overlaps: "[2024-01-01,2024-12-31)" }
}) {
id ip_address location
}
}
```
**[π Nested Array Filtering Guide](https://github.com/fraiseql/fraiseql-python/blob/main/docs/guides/nested-array-filtering.md)**
### Enterprise Security
```python
from fraiseql import authorized
@fraiseql.authorized(roles=["admin", "editor"])
@fraiseql.mutation
class DeletePost:
"""Only admins and editors can delete posts."""
input: DeletePostInput
success: DeleteSuccess
failure: PermissionDenied
# Features:
# - Field-level authorization with role inheritance
# - Row-level security via PostgreSQL RLS
# - Unified audit logging with cryptographic chain (SHA-256 + HMAC)
# - Multi-tenant isolation
# - Rate limiting and CSRF protection
```
### Trinity Identifiers
Three types of identifiers per entity for different purposes:
```python
@fraiseql.type(sql_source="v_post")
class Post(TrinityMixin):
"""
Trinity Pattern:
- pk_post (int): Internal SERIAL key (NOT exposed, only in database)
- id (UUID): Public API key (exposed, stable)
- identifier (str): Human-readable slug (exposed, SEO-friendly)
"""
# GraphQL exposed fields
id: UUID # Public API (stable, secure)
identifier: str | None # Human-readable (SEO-friendly, slugs)
title: str
content: str
# ... other fields
# pk_post is NOT a field - accessed via TrinityMixin.get_internal_pk()
```
**Why three?**
- **pk_\*:** Fast integer joins (PostgreSQL only, never in GraphQL schema)
- **id:** Public API stability (UUID, exposed, never changes)
- **identifier:** Human-friendly URLs (exposed, SEO, readability)
---
## π Get Started in 5 Minutes
```bash
# Install
pip install fraiseql
# Create project
fraiseql init my-api
cd my-api
# Setup database
createdb my_api
psql my_api < schema.sql
# Start server
fraiseql dev
```
**Your GraphQL API is live at ** π
### Next Steps
- **π [First Hour Guide](https://github.com/fraiseql/fraiseql-python/blob/main/docs/getting-started/first-hour.md)** - Build a complete blog API (60 minutes, hands-on)
- **π§ [Understanding FraiseQL](https://github.com/fraiseql/fraiseql-python/blob/main/docs/guides/understanding-fraiseql.md)** - Architecture deep dive (10 minute read)
- **β‘ [5-Minute Quickstart](https://github.com/fraiseql/fraiseql-python/blob/main/docs/getting-started/quickstart.md)** - Copy, paste, run
- **π [Full Documentation](https://github.com/fraiseql/fraiseql-python/tree/main/docs)** - Complete guides and references
### Prerequisites
- **Python 3.13+** (required for Rust pipeline integration and advanced type features)
- **PostgreSQL 13+**
**[π Detailed Installation Guide](docs/getting-started/installation.md)** - Platform-specific instructions, troubleshooting
---
## π¦ Is FraiseQL Right for You?
### β
Perfect For
- **PostgreSQL-first teams** already using PostgreSQL extensively
- **Performance-critical APIs** requiring efficient data access
- **Multi-tenant SaaS** with per-tenant isolation needs
- **Cost-conscious startups** ($5-48K annual savings vs traditional stack)
- **AI-assisted development** teams using Claude/Copilot/ChatGPT
- **Operational simplicity** - one database for everything
- **Self-hosted infrastructure** - full control, no vendor lock-in
### β Consider Alternatives
- **Multi-database support** - FraiseQL is PostgreSQL-specific
- **Simple CRUD APIs** - Traditional REST may be simpler
- **Non-PostgreSQL databases** - FraiseQL requires PostgreSQL
- **Microservices** - Better for monolithic or database-per-service
---
## π οΈ CLI Commands
```bash
# Project management
fraiseql init # Create new project
fraiseql dev # Development server with hot reload
fraiseql check # Validate schema and configuration
# Code generation
fraiseql generate schema # Export GraphQL schema
fraiseql generate types # Generate TypeScript definitions
# Database utilities
fraiseql sql analyze # Analyze query performance
fraiseql sql explain # Show PostgreSQL execution plan
```
---
## Learn More
- **[Full Documentation](https://github.com/fraiseql/fraiseql-python/tree/main/docs)** - Comprehensive guides
- **[Architecture Decisions](https://github.com/fraiseql/fraiseql-python/tree/main/docs/architecture)** - Why we built it this way
- **[Performance Guide](https://github.com/fraiseql/fraiseql-python/blob/main/docs/performance/index.md)** - Optimization strategies
- **[Examples](https://github.com/fraiseql/fraiseql-python/tree/main/examples)** - Real-world applications
---
## Contributing
```bash
git clone https://github.com/fraiseql/fraiseql-python
cd fraiseql-python && make setup-dev
prek install # 7-10x faster than pre-commit
```
[β Contributing Guide](CONTRIBUTING.md)
---
## About
FraiseQL is created by **Lionel Hamayon** ([@evoludigit](https://github.com/evoludigit)).
**The Idea:** What if PostgreSQL returned JSON directly instead of Python serializing it? No ORM. No N+1 queries. No Python overhead. Just Rust transforming JSONB to HTTP.
**The Result:** A GraphQL framework that's 7-10x faster and designed for the LLM era.
---
## License
MIT License - see [LICENSE](LICENSE)
---
## π Project Navigation
### FraiseQL Ecosystem
| Project | Version | Repository | Status | Best For |
|---------|---------|-----------|--------|----------|
| **fraiseql-python** (v1) | v1.9.16 | [fraiseql/fraiseql-python](https://github.com/fraiseql/fraiseql-python) | β
Stable | Python teams, rapid iteration |
| **fraiseql** (v2) | v2.0.0-alpha.2 | [fraiseql/fraiseql](https://github.com/fraiseql/fraiseql) | π Beta | Multi-language, multi-database |
**This Repository:** `fraiseql-python` (v1.9.16 - Python-based with Rust pipeline)
### Quick Navigation
**New to FraiseQL?**
- Start here: **[First Hour Guide](https://github.com/fraiseql/fraiseql-python/blob/main/docs/getting-started/first-hour.md)** (60 min, hands-on)
- Architecture overview: **[Understanding FraiseQL](https://github.com/fraiseql/fraiseql-python/blob/main/docs/guides/understanding-fraiseql.md)** (10 min read)
- Project structure: **[Strategic Overview](https://github.com/fraiseql/fraiseql-python/blob/main/docs/strategic/PROJECT_STRUCTURE.md)**
**Exploring v2?**
- v2 Repository: **[fraiseql/fraiseql](https://github.com/fraiseql/fraiseql)**
- v2 Documentation: **[fraiseql.readthedocs.io](https://fraiseql.readthedocs.io)**
**Troubleshooting:**
- **[Complete Version Roadmap](https://github.com/fraiseql/fraiseql-python/blob/main/dev/audits/version-status.md)** - Version status and feature matrix
---
## π Get Started Now
**Ready to build the most efficient GraphQL API in Python?**
```bash
pip install fraiseql && fraiseql init my-api
```
π Documentation: [github.com/fraiseql/fraiseql-python](https://github.com/fraiseql/fraiseql-python)
π **PostgreSQL β Rust β Production**