Supabase GraphQL — Auto-Generated GraphQL API for PostgreSQL
In this tutorial, you will learn about Supabase Graphql. We cover key concepts, practical examples, and best practices to help you master this topic.
Supabase GraphQL is an auto-generated GraphQL API powered by pg_graphql that instantly creates a GraphQL schema from your PostgreSQL tables, enabling efficient queries that fetch exactly the data you need.
What You'll Learn
By the end of this lesson you will enable the GraphQL extension, write queries and mutations, use GraphQL variables and fragments, filter with complex conditions, and handle relationships between tables.
Why It Matters
GraphQL solves the over-fetching and under-fetching problems of REST. With Supabase's auto-generated GraphQL API, you get these benefits without writing resolvers or schema definitions.
Real-World Use
DodaZIP uses GraphQL on the file management dashboard. A single query fetches user profile, file list with pagination, and processing status -- three REST calls become one efficient GraphQL request.
flowchart LR
A[Client App] -->|GraphQL Query| API[pg_graphql]
API -->|SQL| DB[(PostgreSQL)]
A -->|One request| API
API -->|Nested data| A
style API fill:#3ecf8e,color:#fff
Enabling GraphQL
Enable the GraphQL extension in your Supabase project.
-- Enable the pg_graphql extension
CREATE EXTENSION IF NOT EXISTS pg_graphql;
-- This is done automatically in new Supabase projects
-- Verify it is enabled
SELECT * FROM pg_extension WHERE extname = 'pg_graphql';
# enable_graphql.py
# Enable and verify GraphQL
def graphql_enablement():
print("GraphQL Enablement Checklist:")
print()
print("1. pg_graphql is enabled by default in new projects")
print("2. GraphQL endpoint: https://<project-ref>.supabase.co/graphql/v1")
print("3. Requires same auth headers as REST API")
print("4. Schema is auto-generated from your tables")
print("5. Supports queries, mutations, and subscriptions")
graphql_enablement()
Writing Queries
Fetch exactly the data you need with nested selections.
# Query files with user information
query GetUserFiles {
filesCollection {
edges {
node {
id
name
sizeBytes
mimeType
createdAt
user {
email
fullName
}
}
}
}
}
# Query with filter and pagination
query GetCompletedFiles {
filesCollection(
filter: { status: { eq: "completed" } }
orderBy: { createdAt: DescNullsLast }
first: 10
) {
edges {
node {
id
name
status
createdAt
}
}
}
}
# graphql_queries.py
# Execute GraphQL queries via Python
import requests
import os
def run_graphql_query():
url = os.getenv("SUPABASE_URL", "https://example.supabase.co")
anon_key = os.getenv("SUPABASE_ANON_KEY", "your-anon-key")
query = """
query GetFiles {
filesCollection(first: 5) {
edges {
node {
id
name
sizeBytes
status
}
}
}
}
"""
response = requests.post(
f"{url}/graphql/v1",
headers={
"apikey": anon_key,
"Authorization": f"Bearer {anon_key}",
"Content-Type": "application/json",
},
json={"query": query}
)
data = response.json()
if "errors" in data:
print(f"GraphQL errors: {data['errors']}")
else:
files = data["data"]["filesCollection"]["edges"]
print(f"Query returned {len(files)} files")
for edge in files:
node = edge["node"]
print(f" {node['id']}: {node['name']} ({node['sizeBytes']} bytes)")
run_graphql_query()
Mutations
Insert, update, and delete data via GraphQL mutations.
# Insert a new file
mutation CreateFile {
insertIntofilesCollection(objects: [{
name: "new-doc.pdf"
sizeBytes: 2048000
mimeType: "application/pdf"
userId: "user_abc"
}]) {
records {
id
name
createdAt
}
}
}
# Update a file
mutation UpdateFile {
updatefilesCollection(
set: { status: "archived" }
filter: { id: { eq: "file_123" } }
) {
records {
id
status
}
}
}
# Delete a file
mutation DeleteFile {
deleteFromfilesCollection(
filter: { id: { eq: "file_456" } }
) {
records {
id
}
}
}
# graphql_mutations.py
# GraphQL mutations
def run_mutations():
url = "https://example.supabase.co/graphql/v1"
headers = {"apikey": "your-key", "Authorization": "Bearer your-token"}
# Insert mutation
mutation = """
mutation {
insertIntofilesCollection(objects: [{
name: "test.txt"
sizeBytes: 1000
userId: "user_abc"
}]) {
records { id name }
}
}
"""
response = requests.post(url, headers=headers, json={"query": mutation})
print(f"Insert: {response.json()}")
# Update mutation
mutation = """
mutation {
updatefilesCollection(
set: { status: "completed" }
filter: { name: { eq: "test.txt" } }
) {
records { id status }
}
}
"""
response = requests.post(url, headers=headers, json={"query": mutation})
print(f"Update: {response.json()}")
run_mutations()
Filtering and Pagination
Use GraphQL filter arguments for complex queries.
# graphql_filters.py
# Complex filters and pagination
def filter_examples():
filters = {
"Equals": "filter: { status: { eq: \"completed\" } }",
"Greater than": "filter: { sizeBytes: { gt: 1000000 } }",
"Contains": "filter: { name: { like: \"%report%\" } }",
"AND conditions": "filter: { status: { eq: \"completed\" }, sizeBytes: { gt: 1000 } }",
"OR conditions": "filter: { or: [{ status: { eq: \"active\" } }, { status: { eq: \"pending\" } }] }",
"In list": "filter: { status: { in: [\"active\", \"pending\"] } }",
"Pagination": "first: 10, offset: 20",
"Sorting": "orderBy: { createdAt: DescNullsLast }",
}
print("GraphQL Filter Examples:")
for desc, example in filters.items():
print(f" {desc:20s} | {example}")
filter_examples()
Common Mistakes
Not checking for GraphQL errors: GraphQL always returns 200 status. Check the
errorsfield in the response body for actual errors.Using REST-style authentication: GraphQL uses the same headers as REST API (apikey + Authorization). Missing headers result in permission denied errors.
Forgetting connection-based pagination: GraphQL uses edges and nodes for paginated results. Access
edges[].nodeto reach your data.Writing mutations with wrong names: Mutation names follow the pattern
insertInto<table>Collection,update<table>Collection,deleteFrom<table>Collection.Not using GraphQL variables: Hardcoding values in queries is error-prone. Use variables for dynamic values.
Practice Questions
What extension powers Supabase GraphQL? pg_graphql, which auto-generates a GraphQL schema from PostgreSQL tables.
How do you filter records in a GraphQL query? Use the
filterargument with operators likeeq,gt,like,in.What is the mutation format for inserting data?
insertInto<tableName>Collection(objects: [{...}]) { records { id } }.How do you paginate GraphQL results? Use
first(rows per page) andoffset(skip count) arguments.Challenge: Write a GraphQL query that fetches the 10 most recent files for a specific user, includes the user's email and profile data, and orders by creation date descending.
FAQ
Mini Project
Create a GraphQL query library that provides reusable query functions for common data access patterns: get files by user, search by name, paginate results, and create new files.
class GraphQLClient:
def __init__(self, url, apikey):
self.url = f"{url}/graphql/v1"
self.headers = {"apikey": apikey, "Authorization": f"Bearer {apikey}"}
def query(self, query, variables=None):
response = requests.post(self.url, headers=self.headers, json={"query": query, "variables": variables})
return response.json()
def get_files(self, user_id, limit=10):
q = """
query GetFiles($userId: UUID!, $limit: Int!) {
filesCollection(filter: { userId: { eq: $userId } }, first: $limit) {
edges { node { id name sizeBytes status createdAt } }
}
}
"""
return self.query(q, {"userId": user_id, "limit": limit})
client = GraphQLClient("https://example.supabase.co", "your-key")
result = client.get_files("user_abc", 5)
print(f"Files: {result}")
What's Next
Next: Database Backups for protecting your data.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro