🤖 AI-Native Development
Clear context in SQL functions. Explicit JSONB contracts. No abstraction layers. AI generates correct code on first try.
Code with AI →SQL is one of the most documented languages in existence. LLMs generate it reliably because patterns haven't changed in decades.
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;
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()
Prompt: "Add user authentication to my FraiseQL GraphQL API"
# 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
)
# 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...
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.
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
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
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
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
)
Clear patterns, explicit contracts, type safety. AI generates correct code on first try.