Supabase Agent Skills

repository·main·Indexed 25 days ago

https://github.com/supabase/agent-skills

Official instruction sets and resources designed to enhance AI agents (such as Claude Code, GitHub Copilot, Cursor, and Cline) when working with the Supabase ecosystem. It includes specialized skills for general Supabase development and Postgres performance optimization, covering areas such as database optimization, auth troubleshooting, schema management, and Row-Level Security (RLS).

Tokens
20.2K
Snippets
59
Records
79
Agent score
81%

What's inside supabase-agent-skills

  1. Available Supabase Skills

    main

    The repository provides two primary skills:

    supabase

    A comprehensive development skill covering all Supabase products and integrations. Use for:

    • Working with Database, Auth, Edge Functions, Realtime, Storage, Vectors, Cron, or Queues.
    • Using client libraries (supabase-js, @supabase/ssr) in frameworks like Next.js, React, SvelteKit, Astro, or Remix.
    • Troubleshooting Auth (sessions, JWT, cookies, RLS, etc.).
    • Using the Supabase CLI or MCP server.
    • Schema changes, migrations, security audits, or Postgres extensions (pg_graphql, pg_cron, pg_vector).

    supabase-postgres-best-practices

    Provides Postgres performance optimization guidelines. Use for:

    • Writing SQL queries or designing schemas.
    • Implementing indexes or query optimization.
    • Reviewing database performance or connection pooling.
    • Working with Row-Level Security (RLS).
  2. Understand Postgres Best Practice rule categories

    main

    The supabase-postgres-best-practices skill categorizes Postgres optimization and safety rules into eight distinct sections. Rules are identified by their filename prefix. Use these categories to understand the impact and focus of specific best practice recommendations:

    • Query Performance (query): Focuses on slow queries, missing indexes, and inefficient query plans. (Impact: CRITICAL)
    • Connection Management (conn): Covers connection pooling, limits, and serverless strategies. (Impact: CRITICAL)
    • Security & RLS (security): Covers Row-Level Security (RLS) policies, privilege management, and authentication patterns. (Impact: CRITICAL)
    • Schema Design (schema): Covers table design, index strategies, partitioning, and data type selection. (Impact: HIGH)
    • Concurrency & Locking (lock): Covers transaction management, isolation levels, deadlock prevention, and lock contention. (Impact: MEDIUM-HIGH)
    • Data Access Patterns (data): Covers N+1 query elimination, batch operations, cursor-based pagination, and efficient fetching. (Impact: MEDIUM)
    • Monitoring & Diagnostics (monitor): Covers pg_stat_statements, EXPLAIN ANALYZE, and metrics collection. (Impact: LOW-MEDIUM)
    • Advanced Features (advanced): Covers Full-text search, JSONB optimization, PostGIS, and extensions. (Impact: LOW)
  3. Choose between jsonb_ops and jsonb_path_ops

    main

    When creating a GIN index for jsonb columns, you can choose between two operator classes depending on your query patterns and storage requirements:

    1. jsonb_ops (Default): Supports all JSONB operators. It is more versatile but results in a larger index size.
    2. jsonb_path_ops: Only supports the containment operator (@>). It is significantly more efficient, typically producing an index that is 2-3x smaller than the default.
  4. Secure Row Level Security (RLS) and Database Objects

    main

    Implement RLS following these best practices to avoid common pitfalls:

    • Views and RLS: In Postgres 15+, use CREATE VIEW ... WITH (security_invoker = true) to ensure views respect RLS. For older versions, revoke access from anon/authenticated roles or use a private schema.
    • UPDATE requires SELECT: An UPDATE policy requires a corresponding SELECT policy. Without SELECT access, updates will silently return 0 rows.
    • Use TO instead of auth.role(): The auth.role() function is deprecated. Specify the target role directly using the TO clause (e.g., TO authenticated or TO anon).
    • Avoid BOLA/IDOR: Using TO authenticated only checks the role, not the specific user. Always combine it with an ownership predicate in the USING clause.
    • UPDATE policies: Must include both USING and WITH CHECK to prevent users from reassigning rows to other users.
    • SECURITY DEFINER functions: These bypass RLS. Avoid using them to fix permission errors. If required, keep them in a non-exposed schema, include an auth.uid() check in the body, and use SECURITY INVOKER where possible.

    Correct RLS Patterns

    Authorization with ownership (Correct):

    create policy "example" on table_name for select
    to authenticated
    using ( (select auth.uid()) = user_id );

    Secure UPDATE (Correct):

    create policy "example" on table_name for update
    to authenticated
    using ( (select auth.uid()) = user_id )
    with check ( (select auth.uid()) = user_id );
  5. Core Principles for working with Supabase

    main

    When working with Supabase, follow these fundamental principles to ensure reliability and security:

    1. Verify against current documentation: Supabase features and API signatures change frequently. Always check https://supabase.com/changelog.md for breaking-change tags before implementing new features.
    2. Verify your work: Always run a test query after implementing a fix to confirm it works.
    3. Recover from errors: If an approach fails 2-3 times, stop and reconsider. Check logs and documentation rather than retrying the same command.
    4. Expose tables to the Data API: Newly created tables might not be automatically exposed via the REST API. You may need to explicitly grant access to anon and authenticated roles via SQL GRANT commands. Note that this is separate from Row Level Security (RLS).
    5. Enable RLS in exposed schemas: Always enable RLS on every table in exposed schemas (like public). For private schemas, use RLS as defense in depth.
    6. Security Checklist: Always review security implications for auth, RLS, views, storage, and user data (see specific security records for details).
  6. When to use the Supabase Postgres Best Practices skill

    main

    The supabase-postgres-best-practices skill is a comprehensive guide for Postgres performance optimization and schema design. You should load this skill BEFORE performing any of the following tasks:

    Schema & Data Definition

    • Creating or altering tables and columns (including choosing column types).
    • Schema design and migrations.
    • Declarative schema files.
    • Creating indexes, triggers, database functions, queues, and scheduled jobs (pg_cron, pgmq).
    • Implementing vector/semantic search (pgvector).
    • Restoring dumps (pg_restore) or importing data.

    Security & Logic

    • Writing Row-Level Security (RLS) policies and verification tests.

    Troubleshooting & Optimization

    • Diagnosing slow queries, high CPU, or timeouts.
    • Analyzing EXPLAIN plans.
    • Investigating connection exhaustion, locking, or bloat.
    • Debugging data visibility issues (e.g., rows visible to the wrong user or tenant).
  7. Use Advisory Locks for application-level coordination

    main

    Advisory locks allow you to coordinate application logic (like ensuring only one process runs a specific task) without the overhead of creating dummy rows or using row-level locks. Instead of locking a physical row in a table, you lock an abstract identifier.

    There are two main types of advisory locks in PostgreSQL:

    1. Session-level locks: These persist for the duration of the database connection. You must manually release them using pg_advisory_unlock or they will be released when the session disconnects.
    2. Transaction-level locks: These are automatically released when the current transaction commits or rolls back.
    -- Session-level advisory lock (released on disconnect or unlock)
    select pg_advisory_lock(hashtext('report_generator'));
    -- ... do exclusive work ...
    select pg_advisory_unlock(hashtext('report_generator'));
    
    -- Transaction-level lock (released on commit/rollback)
    begin;
    select pg_advisory_xact_lock(hashtext('daily_report'));
    -- ... do work ...
    commit;  -- Lock automatically released
  8. Secure Supabase Auth and Session Management

    main

    Follow these rules to prevent authentication vulnerabilities:

    • Never use user_metadata for authorization: The raw_user_meta_data field is user-editable and appears in auth.jwt(). It is unsafe for RLS policies. Use raw_app_meta_data / app_metadata instead.
    • Token Invalidation: Deleting a user does not immediately invalidate existing access tokens. For sensitive apps, keep JWT expiry short and validate session_id against auth.sessions for strict guarantees.
    • JWT Freshness: Remember that JWT claims are not always fresh until the user's token is refreshed.
    • Client Exposure: Never expose the service_role or secret key in public clients (e.g., frontend code). In Next.js, avoid putting sensitive keys in NEXT_PUBLIC_ environment variables.
  9. How to access and use individual best practice rules

    main

    Detailed explanations and SQL examples are stored in individual rule files within the references/ directory. You can navigate to specific rules using their prefixed names.

    Each rule file provides:

    • A brief explanation of the rule's importance.
    • An Incorrect SQL example with an explanation of why it is suboptimal.
    • A Correct SQL example with an explanation of the improvement.
    • Optional EXPLAIN output, performance metrics, and additional context.
    • Supabase-specific notes where applicable.

    Example paths:

    • references/query-missing-indexes.md
    • references/query-partial-indexes.md
    • references/_sections.md
  10. Configure PostgreSQL idle connection timeouts

    main

    To prevent idle connections from wasting resources and holding locks, you can configure PostgreSQL to automatically terminate them using idle_in_transaction_session_timeout and idle_session_timeout.

    • idle_in_transaction_session_timeout: Terminates sessions that are idle within an open transaction.
    • idle_session_timeout: Terminates any session that has been idle for the specified duration.

    After applying these settings via ALTER SYSTEM, you must reload the configuration using SELECT pg_reload_conf(); for the changes to take effect.

    -- Terminate connections idle in transaction after 30 seconds
    alter system set idle_in_transaction_session_timeout = '30s';
    
    -- Terminate completely idle connections after 10 minutes
    alter system set idle_session_timeout = '10min';
    
    -- Reload configuration
    select pg_reload_conf();