🤖 AI-Native Development

Built for the LLM Era

Clear context in SQL functions. Explicit JSONB contracts. No abstraction layers. AI generates correct code on first try.

Code with AI →

AI Development Comparison

❌ ORM Magic (AI Struggles)

• Hidden SQL generation
• Complex relationship mapping
• Lazy loading surprises
• Metaclass magic
• Query optimization guesswork
AI generates wrong code frequently

✅ FraiseQL Clarity (AI Excels)

• Explicit SQL functions
• Clear JSONB contracts
• Direct field mapping
• Type hints everywhere
• Predictable patterns
AI generates correct code on first try

Why SQL + Python Wins for AI

SQL: The Ideal LLM Target Language

SQL is one of the most documented languages in existence. LLMs generate it reliably because patterns haven't changed in decades.

  • Fewer tokens: PL/pgSQL is 30-50% shorter than equivalent Python. Cheaper inference.
  • Lower hallucination: Stable syntax since the 1990s. LLMs rarely invent SQL.
  • Single context: Validation, business logic, and data access in one function.
  • Type hints + decorators: Python contract layer LLMs understand perfectly.

Clear Context in PostgreSQL

Business logic lives in PostgreSQL functions with clear names and parameters. AI can understand intent immediately from function names and SQL comments.

-- AI can understand this immediately
CREATE FUNCTION fn_get_user_posts(
    p_user_id int,
    p_limit int DEFAULT 10
) RETURNS jsonb AS $$
    -- Get posts for a specific user
    SELECT jsonb_agg(
        jsonb_build_object(
            'id', p.id,
            'title', p.title,
            'content', p.content
        )
    )
    FROM tb_post p
    WHERE p.fk_author = p_user_id
    AND p.published = true
    ORDER BY p.created_at DESC
    LIMIT p_limit;
$$ LANGUAGE sql SECURITY DEFINER;

Explicit JSONB Contracts

Every field is explicitly defined. No hidden behavior, no magic mapping. AI can see exactly what data is available and how it's structured.

# AI understands this perfectly
@fraiseql.type
class Post:
    id: int              # Primary key
    title: str          # Post title
    content: str        # Full content
    author_id: int      # Who wrote it
    created_at: str     # ISO timestamp
    published: bool     # Is it live?

@fraiseql.query
async def posts(info) -> list[Post]:
    # Clear intent, clear return type
    return await info.context.repo.fetch()

Real AI Development Examples

Claude Code: "Add user authentication"

Prompt: "Add user authentication to my FraiseQL GraphQL API"

✅ What Claude Generates (Correct)

# Clear PostgreSQL function
CREATE FUNCTION authenticate_user(
    p_email text,
    p_password text
) RETURNS jsonb;

# Clear GraphQL type
@fraiseql.type
class AuthResult:
    success: bool
    token: str | None
    user: User | None

@fraiseql.mutation
async def login(info, email: str, password: str) -> AuthResult:
    return await info.context.repo.call_function(
        "authenticate_user", email, password
    )

❌ ORM Alternative (Wrong)

# Complex, error-prone
from sqlalchemy import select
from passlib.hash import pbkdf2_sha256

user = session.execute(
    select(User).where(User.email == email)
).scalar_one_or_none()

if user and pbkdf2_sha256.verify(password, user.password_hash):
    # Complex JWT generation...
    # Session management...
    # Error handling...

GitHub Copilot: "Add filtering"

Prompt: Type @fraiseql.query and let Copilot complete it

# Copilot generates this correctly
@fraiseql.query
async def users(
    info,
    name_filter: str = None,
    age_min: int = None,
    age_max: int = None,
    limit: int = 10
) -> list[User]:
    """
    Get users with optional filtering.
    AI understands: clear parameters, clear return type,
    obvious intent from function name.
    """
    where_clause = {}
    if name_filter:
        where_clause["name__icontains"] = name_filter
    if age_min is not None:
        where_clause["age__gte"] = age_min
    if age_max is not None:
        where_clause["age__lte"] = age_max

    return await info.context.repo.fetch(
        where=where_clause,
        limit=limit
    )

Copilot generates working, type-safe code because FraiseQL patterns are clear and consistent.

No Abstraction Layers Confusing AI

The ORM Abstraction Problem

ORMs hide the database layer behind complex abstractions. AI can't see the actual SQL, making it hard to generate correct queries or understand performance implications.

# What does this actually do?
posts = Post.objects.select_related('author', 'tags').filter(
    published=True,
    author__name__icontains='john'
).prefetch_related('comments')

# AI sees: method chaining, magic methods
# AI doesn't know: joins, indexes, execution plan
# Result: Wrong queries, performance issues

FraiseQL's Direct Approach

Everything is explicit. AI can see the SQL, understand the data flow, and generate correct code because there are no hidden layers.

# AI sees exactly what happens
@fraiseql.query
async def posts(info, author_name: str = None) -> list[Post]:
    # Call PostgreSQL function directly
    return await info.context.repo.call_function(
        "get_posts_by_author",  # Clear function name
        author_name             # Clear parameter
    )

# PostgreSQL function is visible to AI:
-- get_posts_by_author(p_author_name text)
-- Returns posts with author details
-- Uses proper indexes
-- AI can understand and modify this

Type Safety = AI Reliability

Strong Type Hints

Every function parameter and return value is typed. AI can understand data flow and generate correct code.

from typing import List, Optional

@fraiseql.query
async def users(
    info,
    limit: int = 10,                    # Clear type
    offset: int = 0,                    # Clear type
    name_filter: Optional[str] = None   # Clear optional
) -> List[User]:                        # Clear return type
    # AI understands exactly what to return
    pass

Consistent Patterns

Same patterns everywhere. Once AI learns the FraiseQL way, it can generate correct code for any feature.

# AI recognizes this pattern instantly
@fraiseql.type
class Product:
    id: int
    name: str
    price: float

@fraiseql.query
async def products(info) -> List[Product]:
    return await info.context.repo.fetch()

@fraiseql.mutation
async def create_product(info, name: str, price: float) -> Product:
    return await info.context.repo.call_function(
        "create_product", name, price
    )

Ready to Code with AI?

Clear patterns, explicit contracts, type safety. AI generates correct code on first try.