Skip to content

Supabase GraphQL — Auto-Generated GraphQL API for PostgreSQL

DodaTech Updated 2026-06-28 5 min read

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

  1. Not checking for GraphQL errors: GraphQL always returns 200 status. Check the errors field in the response body for actual errors.

  2. Using REST-style authentication: GraphQL uses the same headers as REST API (apikey + Authorization). Missing headers result in permission denied errors.

  3. Forgetting connection-based pagination: GraphQL uses edges and nodes for paginated results. Access edges[].node to reach your data.

  4. Writing mutations with wrong names: Mutation names follow the pattern insertInto<table>Collection, update<table>Collection, deleteFrom<table>Collection.

  5. Not using GraphQL variables: Hardcoding values in queries is error-prone. Use variables for dynamic values.

Practice Questions

  1. What extension powers Supabase GraphQL? pg_graphql, which auto-generates a GraphQL schema from PostgreSQL tables.

  2. How do you filter records in a GraphQL query? Use the filter argument with operators like eq, gt, like, in.

  3. What is the mutation format for inserting data? insertInto<tableName>Collection(objects: [{...}]) { records { id } }.

  4. How do you paginate GraphQL results? Use first (rows per page) and offset (skip count) arguments.

  5. 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

Is the GraphQL API available on all plans?

Yes. GraphQL is available on all Supabase plans, including the free tier.

Does GraphQL support mutations?

Yes. GraphQL supports INSERT, UPDATE, and DELETE mutations auto-generated for each table.

Can I use subscriptions with GraphQL?

Yes. pg_graphql supports subscriptions for real-time data changes.

How do I handle nested relationships?

Use nested fields in your query. Relationships are derived from foreign keys.

Is there a GraphQL playground?

Yes. Supabase provides a GraphQL playground at /graphql/v1 when accessed from a browser.

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