chore(docs) Retire supa-mdx-lint (#50602)

Closes
[DOCS-1289](https://linear.app/supabase/issue/DOCS-1289/get-the-linter-to-fix-what-it-flags-or-retirereplace-the-linter)

Stacked on #50600, which points contributors at the authoring skills.
Merge that one first.

## Problem

Contributors experienced friction with the linter. They felt nickle and
dimed for tiny nits and felt detracted from the work itself. PRs would
become noisy with tiny one-word suggestions.

Additionally, our homegrown linter is not very intelligent, causing
frequent overrides.

## Solution

This removes the linter entirely in favor of directing contributors to
use SKILLS instead.

The removal entails...

- **CI.** Delete the three `docs_lint` workflows: the PR check, the
external-PR comment companion, and the nightly `--fix` bot. Drop the
stale `zizmor.yml` ignore entry for the deleted workflow.
- **Tooling.** Delete `supa-mdx-lint.config.toml` and the 14 rule files.
Drop the `lint:mdx` script and the `@supabase/supa-mdx-lint` dependency
from docs, learn, and ui-library, and regenerate the lockfile.
- **Content.** Remove the 181 directives. A separate commit carries
Prettier's reformatting of the tables and blank lines those comments had
suppressed, so the deletion commit stays readable. No prose changes.
- **Style guide.** The word list states each rule directly instead of
describing what the linter flagged. Every term survives, including the
phrase groups that mirrored `Rule004ExcludeWords`.
- **Skills.** `write-the-docs`, `edit-the-docs`, and `review-the-docs`
drop `pnpm lint:mdx` from their self-review commands and check the word
list directly. `ask-the-docs`'s CI reference drops both workflows.

## Manual testing

1. Run `git grep -i supa-mdx-lint -- . ':!pnpm-lock.yaml'`. No matches.
2. Run `pnpm install --frozen-lockfile --lockfile-only`. It passes, so
the lockfile matches the three trimmed manifests.
3. Run `git diff master...HEAD --name-only --diff-filter=ACMR | grep -E
'\.(md|mdx)$' | xargs npx prettier --config prettier.config.mjs
--check`. All changed markdown passes.
4. Open the [reformatted filter
table](https://docs-git-docs-retire-mdx-linter-supabase.vercel.app/docs/guides/observability/logs#filter-events)
on the preview and compare it with
[production](https://supabase.com/docs/guides/observability/logs#filter-events).
The table renders the same.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Documentation guidance now uses manual prose and terminology review
with the shared word list.
* Clarified storage configuration and common Realtime channel mistakes.
* Improved table formatting, text wrapping, and selected reference
links.
  * Updated documentation authoring and review guidance.

* **Chores**
* Retired automated MDX linting from workflows and local validation
commands.
* Removed lint-suppression markers throughout documentation without
changing instructions.
  * Added targeted documentation review guidance for pull requests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Miranda Limonczenko authored and GitHub committed 2026-09-22 10:00:41 -07:00
1 parent f65ee588c1
commit 7ce4ee53ae
100 files changed
+127 -2043

No files matched your search

@@ -644,8 +644,6 @@ Both of these triggers use the same `util.queue_embeddings` function that will q
Note that the update trigger only fires when the `title` or `content` columns are updated. This is to avoid unnecessary updates to the embedding column when other columns are updated. Make sure that these columns match the columns used in the `embedding_input` function.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### (Optional) Clearing embeddings on update
Note that our trigger will enqueue new embedding jobs when content is updated, but it will not clear any existing embeddings. This means that an embedding can be temporarily out of sync with the content until the new embedding is generated and updated.
-1
View File
@@ -20,7 +20,6 @@ The following example uses text embeddings. Given three phrases:
1. "The cat chases the mouse"
2. "The kitten hunts rodents"
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
3. "I like ham sandwiches"
Your job is to group phrases with similar meaning. If you are a human, this should be obvious. Phrases 1 and 2 are almost identical, while phrase 3 has a completely different meaning.
@@ -229,8 +229,6 @@ order by document_sections.embedding <#> embedding;
<Admonition type="caution">
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
You might be tempted to discard RLS completely and filter by user within the `where` clause. Though this will work, we recommend RLS as a general best practice since RLS is always applied even as new queries and application logic is introduced in the future.
</Admonition>
@@ -206,8 +206,6 @@ As your database scales, you will need an index on your vector columns to mainta
For larger datasets, choosing and tuning the right index is critical for maintaining fast and accurate semantic search.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## pgvector index tuning
When working with embedding datasets at scale (100k+ rows), index selection and tuning can significantly impact query latency and accuracy.
@@ -18,8 +18,6 @@ Supabase provides client libraries for the REST and Realtime APIs. Some librarie
## Community libraries
{/* supa-mdx-lint-disable Rule003Spelling */}
| `Language` | `Source Code` | `Documentation` |
| ----------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------- |
| C# | [supabase-csharp](https://github.com/supabase-community/supabase-csharp) | [Docs](/docs/reference/csharp/introduction) |
@@ -3,8 +3,6 @@ title: A DESCRIPTIVE TITLE
subtitle: A DESCRIPTIVE SUBTITLE
---
{/* supa-mdx-lint-disable */}
{/* Use this template to document Auth Flows. These should be how-to guides, walking the reader through the process of (1) enabling the feature and (2) triggering the flow from their code. */}
A brief description of what this flow does. Don't get into details: if the concepts require a lot of explanation, make a separate page under Concepts.
@@ -148,8 +148,6 @@ var didSendMagicLink = await supabase.Auth.SendMagicLink("valid.email@supabase.i
</$Show>
</Tabs>
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
That's it for the implicit flow.
If you're using PKCE flow, edit the Magic Link [email template](/docs/guides/auth/auth-email-templates) to send a token hash:
@@ -96,8 +96,6 @@ All exceptions originating from the `supabase.Auth` namespace of the C# client l
Below are the most common HTTP status codes you might encounter, along with their meanings in the context of Supabase Auth:
{/* supa-mdx-lint-disable Rule001HeadingCase */}
### [403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403)
Sent out in rare situations where a certain Auth feature is not available for the user, and you as the developer are not checking a precondition whether that API is available for the user.
@@ -118,8 +116,6 @@ Indicate that the Auth server's service is degraded. Most often it points to iss
Sent out when a feature is not enabled on the Auth server, and you are trying to use an API which requires it.
{/* supa-mdx-lint-enable Rule001HeadingCase */}
## Auth error codes table
The following table provides a comprehensive list of error codes you may encounter when working with Supabase Auth. Each error code is associated with a specific issue and includes a description to help you understand and resolve the problem efficiently.
+3 -4
View File
@@ -35,7 +35,6 @@ Registering a passkey requires an existing, confirmed, non-anonymous user. Sign-
### Dashboard
Open the [Passkeys settings](/dashboard/project/_/auth/passkeys) from the **Authentication → Passkeys** section of the Dashboard, turn on **Enable Passkey authentication**, and fill in the WebAuthn [relying party](https://www.w3.org/TR/webauthn-3/#relying-party) details:
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
- **Relying Party Display Name**: a human-readable name for your application shown during the passkey prompt (for example, "My App").
- **Relying Party ID**: the bare domain name for your application (for example, "example.com"). Do not include a scheme, port, or path. This determines which passkeys can be used.
@@ -403,7 +402,7 @@ let response = try await supabase.auth.verifyPasskeyAuthentication(
The `options` field returned from the start methods matches the [WebAuthn `PublicKeyCredentialCreationOptions`](https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialcreationoptions) and [`PublicKeyCredentialRequestOptions`](https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialrequestoptions) shapes (with `ArrayBuffer` fields encoded as base64url).
See the `auth.passkey` reference ([JavaScript](/docs/reference/javascript/auth-passkey-api) · [Dart](/docs/reference/dart/auth-passkey-api) · [Swift](/docs/reference/swift/auth-passkey-api)) for the full API.
See the `auth.passkey` reference ([JavaScript](/docs/reference/javascript/auth-passkey-list) · [Dart](/docs/reference/dart/auth-passkey-list) · [Swift](/docs/reference/swift/auth-passkey-api)) for the full API.
## Manage passkeys
@@ -474,7 +473,7 @@ try await supabase.auth.deletePasskey(id: passkeys.first!.id)
`friendlyName` is limited to 120 characters. `lastUsedAt` is updated each time the passkey is used to sign in.
See the `auth.passkey` reference ([JavaScript](/docs/reference/javascript/auth-passkey-api) · [Dart](/docs/reference/dart/auth-passkey-api) · [Swift](/docs/reference/swift/auth-passkey-api)) for the full API.
See the `auth.passkey` reference ([JavaScript](/docs/reference/javascript/auth-passkey-list) · [Dart](/docs/reference/dart/auth-passkey-list) · [Swift](/docs/reference/swift/auth-passkey-api)) for the full API.
## Admin API
@@ -520,7 +519,7 @@ await supabase.auth.admin.passkey.deletePasskey(
</TabPanel>
</Tabs>
See the `auth.admin.passkey` reference ([JavaScript](/docs/reference/javascript/auth-admin-passkey-api) · [Dart](/docs/reference/dart/auth-admin-passkey-api)) for the full API. The Swift SDK does not expose admin passkey methods.
The Swift SDK does not expose admin passkey methods.
## Error codes
@@ -26,8 +26,6 @@ To maintain the session, these tokens must be stored in a storage medium securel
## Frequently asked questions
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
### No session on the server side with Next.js route prefetching?
When you use route prefetching in Next.js using `<Link href="/...">` components or the `Router.push()` APIs can send server-side requests before the browser processes the access and refresh tokens. This means that those requests may not have any cookies set and your server code will render unauthenticated content.
@@ -38,8 +36,6 @@ To improve experience for your users, we recommend redirecting users to one spec
This is not necessary. Both the access token and refresh token are designed to be passed around to different components in your application. The browser-based side of your application needs access to the refresh token to properly maintain a browser session anyway.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### My server is getting invalid refresh token errors. What's going on?
It is likely that the refresh token sent from the browser to your server is stale. Make sure the `onAuthStateChange` listener callback is free of bugs and is registered relatively early in your application's lifetime
@@ -135,7 +135,6 @@ By default, Supabase Auth uses the _common_ Microsoft tenant (`https://login.mic
If your app is registered as _Personal Microsoft accounts only_ for the _Supported account types_ set Microsoft tenant to _consumers_ (`https://login.microsoftonline.com/consumers`).
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
If your app is registered as _My organization only_ for the _Supported account types_ you may want to configure Supabase Auth with the organization's tenant URL. This will use the tenant's authorization flows instead, and will limit access at the Supabase Auth level to Microsoft accounts arising from only the specified tenant.
Configure this by storing a value under _Azure Tenant URL_ in the Supabase Auth provider configuration page for Azure that has the following format `https://login.microsoftonline.com/<tenant-id>`.
@@ -17,7 +17,6 @@ Setting up Notion sign-in for your application consists of 3 parts:
## Create your notion integration
- Go to [developers.notion.com](https://developers.notion.com/).
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
- Click "View my integrations" and sign in.
![notion.so](/docs/img/guides/auth-notion/notion.png)
-2
View File
@@ -86,8 +86,6 @@ Inviting a user is an admin action, so it must be performed from a trusted serve
2. Click **Add user** and select **Send invitation**.
3. Enter the user's email address and click **Invite user**.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Using the Auth Admin API
Call [`inviteUserByEmail()`](/docs/reference/javascript/auth-admin-inviteuserbyemail) from the SDK's Auth Admin API in a server-side environment. This is part of Supabase Auth (accessed via `supabase.auth.admin` with your project's [secret key](/docs/guides/getting-started/api-keys)), and is distinct from the [Management API](/docs/reference/api/introduction) used to configure your project. You can optionally attach custom `user_metadata` and a redirect URL for the invite link.
@@ -88,16 +88,12 @@ You can insert geographical data through SQL or through our API.
<h4>Restaurants</h4>
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | name | location |
| --- | ----------- | -------------------------------- |
| 1 | Supa Burger | lat: 40.807416, long: -73.946823 |
| 2 | Supa Pizza | lat: 40.807475, long: -73.94581 |
| 3 | Supa Taco | lat: 40.80629, long: -73.945826 |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
<TabPanel id="sql" label="SQL">
@@ -21,8 +21,6 @@ For this guide we'll use the following example data:
>
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description |
| --- | ----------------------------------- | ---------------------- | ------------------------------------------------------------------ |
| 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. |
@@ -31,8 +29,6 @@ For this guide we'll use the following example data:
| 4 | Green Eggs and Ham | Dr. Seuss | Sam has changing food preferences and eats unusually colored food. |
| 5 | Harry Potter and the Goblet of Fire | J.K. Rowling | Fourth year of school starts, big drama ensues. |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
<TabPanel id="sql" label="SQL">
@@ -357,15 +353,11 @@ var result = await supabase
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description |
| --- | ----------------------------------- | ----------------- | ----------------------------------------------- |
| 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. |
| 5 | Harry Potter and the Goblet of Fire | J.K. Rowling | Fourth year of school starts, big drama ensues. |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
</Tabs>
@@ -502,15 +494,11 @@ var result = await supabase
</$Show>
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description |
| --- | --------------------- | ---------------------- | ------------------------------------------- |
| 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. |
| 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
</Tabs>
@@ -609,14 +597,10 @@ var result = await supabase
</$Show>
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description |
| --- | ------ | ----------------- | -------------------------------- |
| 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
</Tabs>
@@ -715,15 +699,11 @@ var result = await supabase
</$Show>
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description |
| --- | --------------------- | ---------------------- | ------------------------------------------- |
| 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. |
| 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
</Tabs>
@@ -1064,14 +1044,10 @@ var result = await supabase
</$Show>
<TabPanel id="data" label="Data">
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | description | fts |
| --- | ------ | ----------------- | -------------------------------- | ------------------------------------------------------- |
| 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | 'big':5 'dream':6 'littl':1 'tootl':7 'toy':2 'train':3 |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
</Tabs>
@@ -117,8 +117,6 @@ values
2. Select the `books` table in the sidebar.
3. Click **+ Insert row** and add 5 rows with the following properties:
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | title | author | metadata |
| --- | ----------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
| 1 | The Poky Little Puppy | Janette Sebring Lowrey | `json {"ages":[3,6],"price":5.95,"description":"Puppy is slower than other, bigger animals."}` |
@@ -127,8 +125,6 @@ values
| 4 | Green Eggs and Ham | Dr. Seuss | `json {"ages":[4,8],"price":7.49,"description":"Sam has changing food preferences and eats unusually colored food."}` |
| 5 | Harry Potter and the Goblet of Fire | J.K. Rowling | `json {"ages":[10,99],"price":24.95,"description":"Fourth year of school starts, big drama ensues."}` |
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
<TabPanel id="js" label="JavaScript">
@@ -27,8 +27,6 @@ connection_string.../postgres?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE
## Errors
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Prepared statement already exists
Supavisor in transaction mode (port 6543) does not support [prepared statements](https://www.postgresql.org/docs/current/sql-prepare.html), which Prisma will try to create in the background.
@@ -18,8 +18,6 @@ Read replicas are additional Supabase Postgres databases kept in sync with your
See [Set up read replicas](/docs/guides/platform/read-replicas).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Pipelines
<$Partial path="pipelines-public-alpha.mdx" />
@@ -8,8 +8,6 @@ sidebar_label: 'ClickHouse'
<$Partial path="pipelines-public-alpha.mdx" />
{/* supa-mdx-lint-disable Rule003Spelling */}
The ClickHouse destination is in private alpha and available only to approved organizations. [Request access](/go/supabase-pipelines-new-destinations) before following this guide.
Replicate Postgres changes to [ClickHouse](https://clickhouse.com/) as current-state tables or an append-only history. [Choose a table engine](#choose-a-table-engine), [prepare resources](#prepare-clickhouse-resources), then [configure the destination](#configure-clickhouse-as-a-destination).
@@ -33,8 +31,6 @@ Choose the engine before creating the pipeline. Changing **Table engine** later
Updating a source primary-key value removes the old key from the current-state view and writes the row under its new key. Changing the primary-key definition is a separate [schema change](#schema-change-support).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Prepare ClickHouse resources
Before creating the destination:
@@ -52,8 +48,6 @@ Keep the database otherwise empty. Pipelines manages the replicated tables and c
The default `ReplacingMergeTree` engine requires ClickHouse 23.5 or later. The `MergeTree` event-log engine does not have this minimum-version requirement.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Configure ClickHouse as a destination
Follow [Set up Pipelines](/docs/guides/database/replication/pipelines#setup-overview) and select **ClickHouse**. Enter these destination settings:
@@ -8,8 +8,6 @@ sidebar_label: 'DuckLake'
<$Partial path="pipelines-public-alpha.mdx" />
{/* supa-mdx-lint-disable Rule003Spelling */}
The DuckLake destination is in private alpha and available only to approved organizations. [Request access](/go/supabase-pipelines-new-destinations) before following this guide.
Replicate Postgres tables to [DuckLake](https://ducklake.select/) for current-state lakehouse queries. [Prepare resources](#understand-the-ducklake-components), [configure the destination](#choose-a-configuration-mode), then [query replicated data](#query-the-destination).
@@ -18,8 +16,6 @@ Replicate Postgres tables to [DuckLake](https://ducklake.select/) for current-st
Insert-only tables don't require a primary key or replica identity. Updates and deletes require a published Postgres row identity. See [supported replica identities](#replica-identity).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Prepare DuckLake resources [#understand-the-ducklake-components]
Prepare a Postgres catalog, object storage, and a compatible query engine:
@@ -32,8 +28,6 @@ Prepare a Postgres catalog, object storage, and a compatible query engine:
You can query replicated tables, but treat them and their underlying catalog and object-storage state as read-only. Writes outside Pipelines can conflict with replication and background maintenance.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Configure DuckLake as a destination [#choose-a-configuration-mode]
Choose a mode below for its resource requirements and configuration steps.
@@ -8,8 +8,6 @@ sidebar_label: 'FAQ'
<$Partial path="pipelines-public-alpha.mdx" />
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Which plans support Pipelines?
Pipelines requires a Pro, Team, or Enterprise plan. During public alpha, availability varies by organization; an eligible plan does not guarantee access. If unavailable, request access from **Database > Replication** or contact your account manager.
@@ -22,8 +20,6 @@ BigQuery is in public alpha. ClickHouse, DuckLake, and Snowflake are in private
Yes. Distance between the source, pipeline, and destination adds network latency and can reduce throughput. Choose resources near the [managed pipeline region](/docs/guides/database/replication/pipelines#region), prioritizing the destination if you can optimize only one side.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## What does Pipelines install in the database?
Pipelines installs objects in your project's Postgres database to track replication and support schema changes:
@@ -42,8 +38,6 @@ The `etl` schema is reserved for Pipelines. If your application already uses a s
To remove the installed objects, delete all pipelines, then [disable Pipelines](#what-happens-when-you-disable-pipelines).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## What does Pipelines check before creating a pipeline?
The Dashboard validates source access, replication capacity, publication tables, and destination connectivity and requirements. **Required** issues block creation; **Warnings** require review. See [creation checks](/docs/guides/database/replication/pipelines#creation-checks).
@@ -95,8 +89,6 @@ Deleting or modifying managed objects can stop replication and require a new ini
Project inactivity stops its pipelines. Start them manually after restarting the project. Downgrading to the Free Plan deletes its pipelines.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## What happens when you disable Pipelines?
Disabling Pipelines removes its database event trigger and the entire Pipelines-managed `etl` schema, including its tables and helper functions. Your source application tables and existing destination data remain.
@@ -39,8 +39,6 @@ Follow your destination guide to prepare its resources and credentials, and chec
- [DuckLake](/docs/guides/database/replication/ducklake)
- [Snowflake](/docs/guides/database/replication/snowflake)
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Step 2: Enable Pipelines
<Admonition type="note">
@@ -175,8 +173,6 @@ A pipeline restart does not request a fresh copy of every table. Tables that com
If the main replication slot is lost and **Recreate slot** is enabled, startup rebuilds all replicated tables. Review [lost-slot recovery](/docs/guides/database/replication/pipelines-monitoring#respond-based-on-the-slot-status) for its data-loss and billing effects. To deliberately rebuild specific tables, use [Restarting tables](/docs/guides/database/replication/pipelines-monitoring#restarting-tables).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Disabling Pipelines
Delete all pipelines first. Then open the three-dot actions menu on the Replication page and click **Disable Pipelines**.
@@ -6,8 +6,6 @@ subtitle: 'Replicate Supabase Postgres changes to Snowflake.'
sidebar_label: 'Snowflake'
---
{/* supa-mdx-lint-disable Rule003Spelling */}
<$Partial path="pipelines-public-alpha.mdx" />
The Snowflake destination is in private alpha and available only to approved organizations. [Request access](/go/supabase-pipelines-new-destinations) before following this guide.
@@ -34,8 +32,6 @@ alter table public.your_table replica identity full;
`REPLICA IDENTITY FULL` increases WAL volume, but lets Pipelines construct complete new rows when Postgres omits unchanged out-of-line TOAST values. The setting applies only to new WAL records. If retained WAL already contains an incompatible update, restart replication for the affected table after changing the setting.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Prepare Snowflake resources
Create a dedicated Snowflake database, schema, role, and service user for Pipelines. Keep the schema otherwise empty to avoid ownership conflicts. Use unquoted identifiers for the service user and role. Pipelines converts the account and user names to uppercase during authentication.
@@ -118,8 +114,6 @@ select current_organization_name() || '-' || current_account_name();
Enter the result as **Account ID**, for example `MYORG-MYACCOUNT`. Do not enter a full URL or dotted locator-and-region hostname. Account IDs can contain up to 63 characters. Legacy one-part account locators are also accepted. See [Snowflake account identifiers](https://docs.snowflake.com/en/user-guide/admin-account-identifier) for details.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Configure Snowflake as a destination
Follow [Set up Pipelines](/docs/guides/database/replication/pipelines#setup-overview) and select **Snowflake**. Enter these settings:
@@ -23,8 +23,6 @@ Tables are where you store your data.
Tables are similar to Excel spreadsheets. They contain columns and rows.
For example, this table has 3 columns named `id`, `name`, and `description`, and 4 rows of data:
{/* supa-mdx-lint-disable Rule003Spelling */}
| `id` | `name` | `description` |
| ---- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | The Phantom Menace | Two Jedi escape a hostile blockade to find allies and come across a young boy who may bring balance to the Force. |
@@ -32,8 +30,6 @@ For example, this table has 3 columns named `id`, `name`, and `description`, and
| 3 | Revenge of the Sith | As Obi-Wan pursues a new threat, Anakin acts as a double agent between the Jedi Council and Palpatine and is lured into a sinister plan to rule the galaxy. |
| 4 | Star Wars | Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a Wookiee and two droids to save the galaxy from the Empire's world-destroying battle station. |
{/* supa-mdx-lint-enable Rule003Spelling */}
There are a few important differences from a spreadsheet, but it's a good starting point if you're new to relational databases.
## Creating and managing tables
@@ -14,16 +14,12 @@ Say you have the following tables from a university database:
**`students`**
{/* supa-mdx-lint-disable Rule003Spelling */}
| id | name | type |
| --- | ---------------- | ------------- |
| 1 | Princess Leia | undergraduate |
| 2 | Yoda | graduate |
| 3 | Anakin Skywalker | graduate |
{/* supa-mdx-lint-enable Rule003Spelling */}
**`courses`**
| id | title | code |
@@ -5,8 +5,6 @@ description: 'Edge Functions can return the following error codes.'
subtitle: 'Understand the error codes returned by Edge Functions to properly debug issues and handle responses.'
---
{/* supa-mdx-lint-disable Rule001HeadingCase */}
When an Edge Function request fails, the response includes a `sb-error-code` header that identifies the specific error.
You can inspect this header in your HTTP client or application code to detect and handle errors programmatically.
@@ -410,8 +410,6 @@ To add Supabase auth per route, use the Hono adapter from `npm:@supabase/server@
---
{/* supa-mdx-lint-disable Rule001HeadingCase */}
## URL Patterns API
If you prefer not to use a web framework, you can directly use [URL Pattern API](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) within your Edge Functions to implement routing.
@@ -5,8 +5,6 @@ description: 'Edge Functions can return following status codes.'
subtitle: 'Understand HTTP status codes returned by Edge Functions to properly debug issues and handle responses.'
---
{/* supa-mdx-lint-disable Rule001HeadingCase */}
When invoking an Edge Function, the response may return a variety of HTTP status codes. The most common status codes are listed below.
<Admonition type="note">
@@ -36,7 +36,6 @@ Postgres is the core of Supabase. We do not abstract the Postgres database—you
- Official Docs: [postgresql.org/docs](https://www.postgresql.org/docs/current/index.html)
- Source code: [github.com/postgres/postgres](https://github.com/postgres/postgres) (mirror)
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
- License: [PostgreSQL License](https://www.postgresql.org/about/licence/)- Language: C
### Studio (dashboard)
@@ -1,7 +1,7 @@
This file is a reference contract for framework quickstarts in this directory. It is
not a rendered page (filenames starting with `_` are excluded from the docs build
and from `supa-mdx-lint`) — it exists so every quickstart conforms to the same shape,
and so Phase 3's lint rule has a single source to check against.
not a rendered page (filenames starting with `_` are excluded from the docs build) — it
exists so every quickstart conforms to the same shape, and so a future automated check
has a single source to check against.
## Required frontmatter
@@ -148,7 +148,6 @@ light file in light mode and the base file in dark mode.
## What's deliberately not in this contract yet
- A machine-checked version of this list (Phase 3 — a `supa-mdx-lint` rule or a
vitest over the MDX AST).
- A machine-checked version of this list (Phase 3 — a vitest over the MDX AST).
- A "last verified" date, pinned framework versions, or a time-to-value label per
guide (Phase 4).
@@ -96,8 +96,6 @@ plugins {
}
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Set up Hilt for dependency injection
In the `build.gradle` (app) file, add the following:
@@ -136,8 +134,6 @@ class MainActivity : ComponentActivity() {
}
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Provide Supabase instances with Hilt
To make the app easier to test, create a `SupabaseModule.kt` file as follows:
@@ -277,8 +277,6 @@ struct UpdateProfileParams: Encodable {
Next, add a way for users to upload a profile photo. Supabase configures every project with [Storage](/docs/guides/storage) for managing large files like photos and videos.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Add `PhotosPicker`
Add support for the user to pick an image from the library and upload it.
@@ -322,8 +320,6 @@ enum TransferError: Error {
</$CodeTabs>
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### Add `PhotosPicker` to profile page
<$CodeTabs>
@@ -13,8 +13,6 @@ Using OAuth2.0 you can retrieve an access and refresh token that grant your appl
2. In the upper-right section of the page, click **Add application**.
3. Fill in the required details and click **Confirm**.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Show a "Connect Supabase" button
In your user interface, add a "Connect Supabase" button to kick off the OAuth flow. Follow the design guidelines outlined in our [brand assets](/brand-assets).
@@ -18,18 +18,15 @@ Without a log type selection, Logs queries **Postgres** and **API Gateway**. Sel
## Filter events
{/* supa-mdx-lint-disable Rule003Spelling */}
| Filter | Behavior |
| Filter | Behavior |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Log Type | Select API Gateway, Postgres, Auth, Storage, PostgREST, Edge Function, Realtime, or pooler events. |
| Level | Match success, warning, or error. |
| Status | Match an HTTP status or Postgres SQLSTATE. |
| Method | Match an HTTP method. |
| Pathname | Match a request path. |
| Log Type | Select API Gateway, Postgres, Auth, Storage, PostgREST, Edge Function, Realtime, or pooler events. |
| Level | Match success, warning, or error. |
| Status | Match an HTTP status or Postgres SQLSTATE. |
| Method | Match an HTTP method. |
| Pathname | Match a request path. |
| Event message | Use **iLike** or **Not iLike** for case-insensitive text matching or exclusion. Plain text matches anywhere in the message; `%` specifies a wildcard pattern. |
| User | Match the user's ID in Auth actor IDs or API Gateway JWT subjects. Other log types cannot match this filter. |
{/* supa-mdx-lint-enable Rule003Spelling */}
| User | Match the user's ID in Auth actor IDs or API Gateway JWT subjects. Other log types cannot match this filter. |
Filters other than **Event message** and **User** support **Equals** and **Not equal**. **User** supports **Equals**. Included values within a field match any selected value; exclusions remove every selected value. Filters on different fields must all match.
@@ -93,8 +93,6 @@ The following charts are available for Free and Pro plans:
| Disk usage | Free, Pro | Disk space consumption breakdown | Storage capacity planning |
| Database size | Free, Pro | Total database size and growth trends | Space consumption monitoring, including list of largest tables |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Advanced Telemetry
{/* TODO: This is confusing and feels contradictory */}
@@ -351,8 +349,6 @@ Actions you can take:
| Implement [connection pooling](/docs/guides/database/connecting-to-postgres#choose-a-connection-method) | Optimize connection management for high direct connection usage |
| Review application code | Ensure proper connection handling and cleanup |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Dedicated Pooler (PgBouncer) Client Connections
Available on Team and Enterprise plans.
@@ -375,8 +371,6 @@ Actions you can take:
| Implement [connection pooling](/docs/guides/database/connecting-to-postgres#choose-a-connection-method) | Optimize connection management for high direct connection usage |
| Review application code | Ensure proper connection handling and cleanup |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Shared Pooler (Supavisor) Client Connections
Available on Team and Enterprise plans.
@@ -5,8 +5,6 @@ description: 'This documentation covers frequently asked questions around subscr
subtitle: 'This documentation covers frequently asked questions around subscription plans, payments, invoices and billing in general'
---
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
## Organizations and projects
### What are organizations and projects?
@@ -61,8 +61,6 @@ height={758}
## Credit FAQ
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
### Will I get an invoice for the credits purchase?
Yes, once the payment is confirmed, you will get a matching invoice that can be accessed through your [organization's invoices page](/dashboard/org/_/billing#invoices).
@@ -90,7 +90,6 @@ Use the [`domains reverify`](/docs/reference/cli/supabase-domains-reverify) comm
supabase domains reverify --project-ref abcdefghijklmnopqrst
```
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
In the background, Supabase will check your DNS records and issue an SSL certificate. Supabase uses multiple Certificate Authorities (including Let's Encrypt, Google Trust Services and SSL.com) to ensure high availability. The specific issuer is chosen based on availability and this process can take up to 30 minutes.
### Prepare to activate your domain
@@ -3,7 +3,6 @@ title: 'Project Pausing'
description: 'Free project pausing behavior.'
---
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Supabase pauses Free Plan projects that show low activity over a 7-day period to save server resources. This guide explains how pausing works, how to restore a paused project, and how to avoid pausing altogether.
<Admonition type="note">
@@ -33,20 +33,14 @@ Read Replicas run on the same Compute size as the primary database.
Read [the Manage Disk Size usage guide](/docs/guides/platform/manage-your-usage/disk-size) for details on how we calculate charges. The disk size of a Read Replica is 1.25x the size of the primary disk to account for WAL archives. With a Read Replica you go beyond your subscription plan's quota for Disk Size.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Provisioned Disk IOPS (optional)
Read Replicas inherit any additional provisioned Disk IOPS from the primary database. Read the [Manage Disk IOPS usage guide](/docs/guides/platform/manage-your-usage/disk-iops) for details on how we calculate charges.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Provisioned Disk Throughput (optional)
Read Replicas inherit any additional provisioned Disk Throughput from the primary database. Read the [Manage Disk Throughput usage guide](/docs/guides/platform/manage-your-usage/disk-throughput) for details on how we calculate charges.
{/* supa-mdx-lint-enable-next-line Rule001HeadingCase */}
### IPv4 (optional)
If the primary database has configured an IPv4 address add-on, its Read Replicas are also assigned one, with charges for each. Read the [Manage IPv4 usage guide](/docs/guides/platform/manage-your-usage/ipv4) for details on how we calculate charges.
@@ -349,8 +349,6 @@ ssl = on
listen_addresses = '*' # Or specific IP addresses
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### pg_hba.conf
```bash
@@ -61,7 +61,6 @@ Supabase will send you an AWS Resource Share containing the VPC Lattice Resource
1. Sign in to your AWS Management Console, ensure you are in the AWS region where your Supabase project is located
2. Navigate to the AWS Resource Access Manager (RAM) console
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
3. Go to [Shared with me > Resource shares](https://console.aws.amazon.com/ram/home#SharedResourceShares)
4. Locate the resource share from Supabase.
- The resource share has the format `sspl-[project_ref]-[random alphanumeric string]`
@@ -70,7 +69,6 @@ Supabase will send you an AWS Resource Share containing the VPC Lattice Resource
6. Click **Accept resource share**
7. Confirm the acceptance in the dialog box
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
After accepting, you'll see the resource configurations appear in your [Shared with me > Shared resources](https://console.aws.amazon.com/ram/home#SharedResources) section of the RAM console and the [PrivateLink and Lattice > Resource configurations](https://console.aws.amazon.com/vpcconsole/home#ResourceConfigs) section of the VPC console.
### Step 3: Configure security groups
@@ -150,8 +150,6 @@ You can find additional resources on replication lag in [the Google documentatio
## Troubleshooting
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### An "Init failed" status
The replica status "Init failed" in the dashboard indicates that the Read Replica has failed to deploy. Some possible scenarios as to why a Read Replica deployment may have failed are the following:
@@ -163,5 +161,3 @@ The replica status "Init failed" in the dashboard indicates that the Read Replic
- Very high active workloads combined with large (50+ GB) database sizes
It is safe to drop this failed Read Replica, and in the event of a transient issue, attempt to spin up another one. If spinning up Read Replicas for your project consistently fails, check the[status page](https://status.supabase.com) for any ongoing incidents, or [open a support ticket](/dashboard/support/new). To aid the investigation, do not bring down the recently failed Read Replica.
{/* supa-mdx-lint-enable-next-line Rule001HeadingCase */}
@@ -49,8 +49,6 @@ height={2192}
5. Usage based fee for Egress for the previous billing cycle. There is a free usage quota of 250 GB for Egress. You get charged for usage beyond 250 GB only, meaning for 2,119.47 GB. The final Egress fees are <Price price="190.75" />.
6. Usage based fee for Monthly Active Users for the previous billing cycle. There is a free usage quota of 100,000 users. With 141 users there is no charge for this line item.
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
### Why is my invoice more than <Price price="25" />?
The amount due of your invoice being higher than the <Price price="25" /> subscription fee for the Pro Plan can have several reasons.
@@ -26,8 +26,6 @@ Phoenix is fast and able to handle millions of concurrent connections.
Phoenix can handle many concurrent connections because Elixir provides lightweight processes (not OS processes) to work with.
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
Client-facing WebSocket servers need to handle many concurrent connections. Elixir & Phoenix let the Supabase Realtime cluster do this easily.
## Channels
@@ -491,7 +491,6 @@ Broadcast payloads can be binary (`ArrayBuffer` or `ArrayBufferView`, e.g. `Uint
</TabPanel>
</$Show>
</Tabs>
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Broadcast from the Database
@@ -11,7 +11,6 @@ To start the connection we use the WebSocket URL, which for:
- Supabase projects: `wss://<PROJECT_REF>.supabase.co/realtime/v1/websocket?apikey=<API_KEY>`
- self-hosted projects: `wss://<HOST>:<PORT>/socket/websocket?apikey=<API_KEY>`
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
As an example, using [websocat](https://github.com/vi/websocat), you would run the following command in your terminal:
```bash
@@ -114,8 +113,6 @@ The two special message types have a well defined binary format where the first
| 3 | USER_BROADCAST_PUSH | User-initiated broadcast push |
| 4 | USER_BROADCAST | User broadcast message |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### User Broadcast Push
```
@@ -199,8 +196,6 @@ Messages for all events are encoded as text frames using JSON except with the `b
| `broadcast` | Broadcast message sent to all clients in a channel | ✅ | ✅ |
| `presence` | Presence state update sent after joining a channel | ✅ | ✅ |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### phx_join
This is the initial message required to join a channel. The client sends this message to the server to join a specific topic and configure the features it wants to use, such as Postgres changes, Presence, and Broadcast. The payload of the `phx_join` event contains the configuration options for the channel.
@@ -285,8 +280,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### phx_leave
This message is sent by the client to leave a channel. It can be used to clean up resources or stop listening for events on that channel. Payload should be empty object.
@@ -297,8 +290,6 @@ Example on protocol version `2.0.0`:
["1", "3", "realtime:avatar-stack-demo", "phx_leave", {}]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### heartbeat
The heartbeat message should be sent at least every 25 seconds to avoid a connection timeout. Payload should be an empty object.
@@ -311,8 +302,6 @@ Example on protocol version `2.0.0`:
[null, "26", "phoenix", "heartbeat", {}]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### access_token
Used to setup a new token to be used by Realtime for authentication and to refresh the token to prevent a private channel from closing when the token expires.
@@ -339,8 +328,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### broadcast (text frame)
Used to send a broadcast event to all clients in a channel.
@@ -380,8 +367,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### broadcast (binary frame)
See the [User Broadcast Push](#user-broadcast-push) section for the binary frame structure.
@@ -419,8 +404,6 @@ user-event // User Event
The payload encoding is a hint for the client to know if the payload should be treated as JSON or not.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### presence
Used to send presence metadata after joining a channel. The payload contains the presence information to be tracked by the server.
@@ -466,8 +449,6 @@ Example on protocol version `2.0.0`:
| `presence_diff` | Presence state diff update sent after a change in presence state | ⛔ | ⛔ |
| `postgres_changes` | Postgres CDC message containing changes to the database | ⛔ | ⛔ |
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### phx_close
This message is sent by the server to signal that the channel has been closed. Payload will be empty object.
@@ -478,8 +459,6 @@ Example on protocol version `2.0.0`:
["3", "3", "realtime:avatar-stack-demo", "phx_close", {}]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### phx_error
This message is sent by the server when the channel process terminates unexpectedly. Payload will be an empty object. See [Reconnection](#reconnection) for recovery guidance.
@@ -488,8 +467,6 @@ This message is sent by the server when the channel process terminates unexpecte
["3", "3", "realtime:avatar-stack-demo", "phx_error", {}]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### phx_reply
The server sends these messages in response to client requests that require acknowledgment.
@@ -551,8 +528,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### system
The server sends system messages to inform clients about the status of their Realtime channel subscriptions. See [Channel-level system errors](#channel-level-system-errors) for the full list of messages and recovery actions.
@@ -605,12 +580,8 @@ When a channel is joined with `config.broadcast.replication_ready` set to `true`
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### broadcast (text frame)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
This is the structure of broadcast events received by all clients subscribed to a channel. The `payload` field contains the event name and data that was broadcasted.
```ts
@@ -656,8 +627,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### broadcast (binary frame)
See the [User Broadcast](#user-broadcast) section for the binary frame structure.
@@ -690,8 +659,6 @@ message // User Event
The metadata field is JSON encoded. The payload encoding is a hint for the client to know if the payload should be treated as JSON or not.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### postgres_changes
The server sends this message when a database change occurs in a subscribed schema and table. The payload contains the details of the change, including the schema, table, event type, and the new and old records.
@@ -779,8 +746,6 @@ When the subscription was joined with a `select` array (see [phx_join](#phx_join
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### presence_state
After joining, the server sends a `presence_state` message to a client with presence information. The payload field contains keys, where each key represents a client and its value is a JSON object containing information about that client. The key is defined by the client when joining the channel. If not specified, a UUID is automatically generated.
@@ -843,8 +808,6 @@ Example on protocol version `2.0.0`:
]
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
#### presence_diff
After a change to the presence state, such as a client joining or leaving, the server sends a presence_diff message to update the client's view of the presence state. The payload field contains two keys, `joins` and `leaves`, which represent clients that have joined and left, respectively. Each key is either specified by the client when joining the channel or automatically generated as a UUID.
@@ -921,8 +884,6 @@ Errors arrive on four channels:
- A `system` event on a live channel — channel-level system errors are always followed by `phx_close`, while `postgres_changes` system errors are informational and leave the channel open.
- A `phx_error` when the channel process terminates unexpectedly.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Join errors
When a `phx_join` is rejected, the `phx_reply` payload carries `response.reason` as `"<ErrorCode>: <human message>"`. The server adds a backoff delay before replying, so avoid aggressive client-side retry loops on join errors.
@@ -3,8 +3,6 @@ title: 'Realtime Reports'
description: 'Reports to help debug Realtime issues'
---
{/* supa-mdx-lint-disable Rule001HeadingCase */}
Realtime reports give insights into how your application uses Supabase Realtime, including connections, broadcast and change events, execution times, and lag.
These reports help you:
@@ -65,8 +65,6 @@ Determines the number of connections used to create [Postgres Changes](/docs/gui
Raise this value if many clients subscribe at the same time, such as after a deploy or a mass reconnect.
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
### Max concurrent clients
**Type:** Number of clients · **Range:** 1 to your plan's [concurrent connections](/docs/guides/realtime/limits#limits-by-plan) limit · **Default:** your plan's limit
@@ -4,7 +4,6 @@ description: 'Copy storage objects from a managed Supabase project to a self-hos
subtitle: 'Copy storage objects from a managed Supabase project to a self-hosted instance using rclone.'
---
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
This guide walks you through copying storage objects from a managed Supabase platform project to a self-hosted instance using [rclone](https://rclone.org/) with S3-to-S3 copy.
<Admonition type="caution">
@@ -20,7 +19,6 @@ You need:
- A working self-hosted Supabase instance with the S3 protocol endpoint enabled - see [Configure S3 Storage](/docs/guides/self-hosting/self-hosted-s3#enable-the-s3-protocol-endpoint)
- Your platform project's S3 credentials - generated from the [S3 Configuration](/dashboard/project/_/storage/s3) page
- Matching buckets created on your self-hosted instance
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- [rclone](https://rclone.org/install/) installed on the machine running the copy
## Step 1: Get platform S3 credentials
@@ -64,11 +62,8 @@ on conflict (id) do nothing;
Repeat for each bucket, setting `public` to `true` or `false` as appropriate.
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
## Step 3: Configure rclone
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Create or edit your rclone configuration file (`~/.config/rclone/rclone.conf`):
```ini rclone.conf
@@ -141,17 +136,14 @@ Open Studio on your self-hosted instance and browse the storage buckets to confi
If you see `SignatureDoesNotMatch` when connecting to either remote:
- **Platform**: Regenerate S3 access keys from your project's Storage Settings. Ensure the endpoint URL includes `/storage/v1/s3`.
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **Self-hosted**: Verify that `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` in `.env` file match your rclone config.
### Bucket not found
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
If rclone reports that a bucket doesn't exist on the self-hosted side, create it first - see [Step 2](#step-2-create-buckets-on-self-hosted). The S3 protocol does not auto-create buckets on copy.
### Timeouts on large files
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
For very large files, increase rclone's timeout:
```sh
@@ -40,7 +40,6 @@ You need the following installed on your system:
- **Linux desktop**: Install [Docker Desktop](https://docs.docker.com/desktop/setup/install/linux/)
- **macOS**: Install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/)
- **Windows**: Install [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
## System requirements
@@ -441,7 +440,6 @@ Everything beyond this point in the guide helps you understand how the system wo
Supabase is built from open source tools, each chosen or developed for production use.
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
If the tools and communities already exist, with an MIT, Apache 2, PostgreSQL, or equivalent open source license, we will use and support that tool. If the tool doesn't exist, we build and open source it ourselves.
<Image
@@ -461,7 +459,6 @@ If the tools and communities already exist, with an MIT, Apache 2, PostgreSQL, o
- **[PostgREST](https://github.com/PostgREST/postgrest)** - Web server that turns your Postgres database directly into a RESTful API
- **[Realtime](https://github.com/supabase/realtime)** - Elixir server that listens to Postgres database changes and broadcasts them to subscribed clients
- **[Storage](https://github.com/supabase/storage)** - RESTful API for managing files in S3, with Postgres handling permissions
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **[imgproxy](https://github.com/imgproxy/imgproxy)** - Fast and secure image processing server
- **[postgres-meta](https://github.com/supabase/postgres-meta)** - RESTful API for managing Postgres (fetch tables, add roles, run queries)
- **[Postgres](https://github.com/supabase/postgres)** - Object-relational database with over 30 years of active development
@@ -524,7 +521,6 @@ The `generate-keys.sh` script sets the following secrets automatically. You can
- `LOGFLARE_PRIVATE_ACCESS_TOKEN`: API token for Logflare management operations. Used by Studio for administrative tasks. Never expose client-side. (Must be at least 32 characters; generate with `openssl rand -base64 24`)
- `S3_PROTOCOL_ACCESS_KEY_ID`: Access key ID (username-like) for [accessing](/docs/guides/self-hosting/self-hosted-s3) the S3 protocol endpoint in Storage. (Generate with `openssl rand -hex 16`)
- `S3_PROTOCOL_ACCESS_KEY_SECRET`: Secret key (password-like) used with S3_PROTOCOL_ACCESS_KEY_ID. (Generate with `openssl rand -hex 32`)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- `MINIO_ROOT_PASSWORD`: Root administrator password for the [RustFS or MinIO server](/docs/guides/self-hosting/self-hosted-s3). (Must be 8+ characters; generate with `openssl rand -hex 16`)
### Configuring Supabase services
@@ -576,14 +572,12 @@ SMTP_SENDER_NAME=your-sender-name
We recommend using [AWS SES](https://aws.amazon.com/ses/). It's affordable and reliable. Restart all services to pick up the new configuration.
### Configuring S3 Storage
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
By default, when using self-hosted Storage service, all files are stored locally on your server filesystem (via a bind mount in `docker-compose.yml`). You can connect Storage to an S3-compatible backend (AWS S3, RustFS, MinIO, Cloudflare R2), enable the S3 protocol endpoint for tools like `rclone`, or both. These are independent features.
See the [Configure S3 Storage](/docs/guides/self-hosting/self-hosted-s3) guide for detailed setup instructions.
### Using file backend in Storage on macOS
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
By default, the Storage backend uses local files via a bind mount. On macOS, Docker Desktop bind mounts have known limitations (missing xattr support, permission issues) that can prevent Storage from working correctly. Change the [bind mount](https://github.com/supabase/supabase/blob/a5f4a59e0e262394b345600e8d8a2241d6ac3b64/docker/docker-compose.yml#L391) to a named Docker volume instead.
### Configuring Supabase AI Assistant
@@ -25,7 +25,6 @@ On a fresh Postgres 17 deployment, the `pg_graphql` extension is **disabled by d
</Admonition>
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
If the new Postgres 17 container fails to start, make sure to check for an old `db-config` Docker volume. See [Postgres 17 fails to start with a leftover db-config volume](#postgres-17-fails-to-start-with-a-leftover-db-config-volume) for details.
## Upgrade an existing Postgres 15 deployment
@@ -199,8 +198,6 @@ After both phases, the upgrade script applies migrations that normally run only
## Troubleshooting
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### pg_upgrade fails with replication slot errors
`pg_upgrade` cannot proceed if there are active replication slots. Default self-hosted installs don't have any, but if you set up logical replication or have custom replication configurations, drop the slots before upgrading:
@@ -223,8 +220,6 @@ docker compose run --rm db \
chown -R postgres:postgres /var/lib/postgresql/data
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### pgsodium / Supabase Vault errors
The `db-config` named volume contains the pgsodium root encryption key at `/etc/postgresql-custom/pgsodium_root.key`. This volume is preserved during the upgrade. Never run `docker compose down -v` as this destroys named volumes and makes vault secrets unrecoverable.
@@ -253,8 +248,6 @@ sudo TMPDIR=/mnt/my-tmp bash utils/upgrade-pg17.sh
If you run out of space mid-upgrade, the safest path is to roll back and free up disk space before retrying.
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Postgres 17 fails to start with a leftover db-config volume
If you are starting a **fresh** Postgres 17 deployment (not using the upgrade script) and the container fails to start, the most likely cause is a leftover `db-config` volume from a previous Postgres 15 installation. Start the containers without the `-d` option or check the logs for errors about `postgresql.conf` or other configuration mismatch.
@@ -8,8 +8,6 @@ You can configure self-hosted Supabase to use the [publishable and secret API ke
## Before you begin
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- Complete the [Docker setup guide](/docs/guides/self-hosting/docker) so that `JWT_SECRET`, `ANON_KEY`, and `SERVICE_ROLE_KEY` are set in your `.env` file. [Quick start (Linux)](/docs/guides/self-hosting/docker#quick-start-linux) handles this automatically; the manual path runs [`generate-keys.sh`](/docs/guides/self-hosting/docker#generate-keys-and-secrets).
- If you are upgrading from a legacy self-hosted Supabase environment, make sure to check the [changelog](https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md#2026-03-16) and [add/update](/docs/guides/self-hosting/updating) the following files:
- `.env.example` (merge new sections into your `.env` file)
@@ -8,8 +8,6 @@ Self-hosted Supabase uses an [Envoy](https://www.envoyproxy.io/)-based API gatew
This guide explains the architecture, configuration layout, and security posture of the Envoy gateway for operators who want to understand or customize it. It is not an Envoy tutorial - for reference on filters, routes, and clusters, see the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/).
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
## Using the gateway
Envoy is the default API gateway and runs automatically when you start the stack - no extra configuration is required.
@@ -66,8 +66,6 @@ GOOGLE_CLIENT_ID=your-client-id
GOOGLE_SECRET=your-client-secret
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Step 3: Enable the matching lines in Docker Compose configuration
Uncomment the corresponding `GOTRUE_EXTERNAL_` lines in the `auth` service's `environment`:
@@ -407,8 +405,6 @@ After a successful OAuth sign-in, the Auth service redirects to `SITE_URL` or a
- `SITE_URL` in `.env` is set to your **application's URL**
- If your app uses a different redirect URL, add it to `ADDITIONAL_REDIRECT_URLS` (comma-separated)
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Nonce check failure on mobile (Google Sign In)
When using Google Sign In on mobile with ID tokens, nonce verification may fail because mobile SDKs don't always support the nonce flow that the Auth service expects.
@@ -40,8 +40,6 @@ SMS_TWILIO_AUTH_TOKEN=your-auth-token
SMS_TWILIO_MESSAGE_SERVICE_SID=your-message-service-sid
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Step 2: Uncomment the matching lines in Docker Compose configuration
Uncomment the `GOTRUE_SMS_*` lines in the `auth` service's `environment` block:
@@ -4,8 +4,6 @@ description: 'Set up a reverse proxy with HTTPS for self-hosted Supabase.'
subtitle: 'Set up a reverse proxy with HTTPS for self-hosted Supabase.'
---
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
HTTPS is required for production self-hosted Supabase deployments. This guide covers two production approaches using a reverse proxy in front of self-hosted Supabase API gateway, plus a self-signed certificate option for development environment.
## Before you begin
@@ -135,8 +133,6 @@ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
chgrp 65533 volumes/api/server.key
```
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
### Step 2: Configure Kong for SSL
Comment out Kong's **HTTP** port mapping in `docker-compose.yml`:
@@ -5,10 +5,8 @@ subtitle: 'Enable S3-compatible client endpoint and set up an S3 backend for sel
---
Self-hosted Supabase Storage has two independent S3-related features:
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **S3 protocol endpoint** - an S3-compatible API that Storage exposes at `/storage/v1/s3`. This allows standard S3 tools like `rclone` and the AWS CLI to interact with your Storage instance.
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **S3 backend** - where Storage keeps data. By default, files are stored on the local filesystem. You can switch to an S3-compatible service (AWS S3, MinIO, etc.) for durability, scalability, or to use existing infrastructure.
You can configure either feature independently. For example, you can enable the S3 protocol endpoint to use `rclone` while keeping the default file-based storage, or switch to an S3 backend without enabling the S3 protocol endpoint.
@@ -42,8 +40,6 @@ aws s3 ls \
s3://your-storage-bucket )
```
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Test with rclone
```sh
@@ -79,15 +75,10 @@ storage:
REGION: your-region
```
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Depending on your setup, you may need to adjust these values - for example, to use a local S3-compatible service like RustFS, MinIO or a cloud provider like AWS.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Using RustFS
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
An override `docker-compose.rustfs.yml` can be added to enable RustFS container and provide an S3-compatible API for Storage backend:
```sh
@@ -97,19 +88,14 @@ sh run.sh start
Make sure to review the Storage section in your `.env` file for related configuration options.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
### Using MinIO
<Admonition type="note">
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
MinIO no longer publishes open source Docker images or maintains their open source repository. The MinIO configuration is provided for backward compatibility and uses images built by [Chainguard](https://images.chainguard.dev/directory/image/minio/overview) (`cgr.dev/chainguard/minio`). For new deployments, consider using [RustFS](#using-rustfs) instead.
</Admonition>
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
An override `docker-compose.s3.yml` can be added to enable MinIO container and provide an S3-compatible API for Storage backend:
```sh
@@ -138,7 +124,6 @@ For AWS S3, you do not need `GLOBAL_S3_ENDPOINT` or `GLOBAL_S3_FORCE_PATH_STYLE`
### S3-compatible providers
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Use the same configuration as MinIO, replacing the endpoint, bucket name, region, and AWS credentials with the values provided by your S3-compatible provider, for example:
```yaml name=docker-compose.yml
@@ -156,8 +141,6 @@ storage:
## Verify the setup
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- Open Studio and upload a file to a bucket. List the file using the AWS CLI or `rclone` to confirm the S3 endpoint works.
- If using an S3 backend: confirm the file appears in your S3 provider's console.
@@ -4,7 +4,6 @@ description: 'Set up SAML 2.0 Single Sign-On for self-hosted Supabase with Docke
subtitle: 'Set up SAML 2.0 Single Sign-On for self-hosted Supabase with Docker.'
---
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
SAML 2.0 SSO lets your users authenticate through an enterprise Identity Provider (IdP) such as Okta, Azure AD (Entra ID), Google Workspace, or any SAML 2.0-compliant provider. Unlike OAuth providers, SAML IdPs are not configured through environment variables - they are managed dynamically at runtime through the Auth admin API.
This guide covers the full setup: generating a signing key, enabling SAML in your Supabase instance, registering an IdP, and integrating SSO into your application.
@@ -138,21 +137,18 @@ This returns an XML document containing your SP entity ID, ACS endpoint URL, and
<Admonition type="note">
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Add `?download=true` to the request URL to get the metadata as a downloadable XML file with a 5-year validity period - this is useful for IdPs that require a file upload instead of a URL.
</Admonition>
Key values in the metadata:
{/* supa-mdx-lint-disable Rule003Spelling */}
| Field | Value |
|---|---|
| Entity ID | `{API_EXTERNAL_URL}/sso/saml/metadata` |
| ACS URL | `{API_EXTERNAL_URL}/sso/saml/acs` |
| NameID formats | `persistent`, `emailAddress` |
| Signing certificate | Derived from your `SAML_PRIVATE_KEY` |
{/* supa-mdx-lint-enable Rule003Spelling */}
| Field | Value |
| ------------------- | -------------------------------------- |
| Entity ID | `{API_EXTERNAL_URL}/sso/saml/metadata` |
| ACS URL | `{API_EXTERNAL_URL}/sso/saml/acs` |
| NameID formats | `persistent`, `emailAddress` |
| Signing certificate | Derived from your `SAML_PRIVATE_KEY` |
## Step 6: Register an identity provider
@@ -200,7 +196,6 @@ curl -X POST 'http://<your-domain>/auth/v1/admin/sso/providers' \
<Admonition type="note">
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
When using `metadata_url`, the URL must use HTTPS. Auth validates the metadata XML format and checks that the EntityID is unique across all registered providers.
</Admonition>
@@ -224,31 +219,27 @@ The response includes the provider `id` (UUID) - save this for use in your appli
### Registration parameters reference
{/* supa-mdx-lint-disable Rule003Spelling */}
| Parameter | Required | Description |
|---|---|---|
| `type` | Yes | Must be `"saml"` |
| `metadata_url` | One of these | HTTPS URL to the IdP's SAML metadata (auto-refreshed) |
| `metadata_xml` | One of these | Raw IdP metadata XML string |
| `domains` | No | Array of email domains to associate (e.g., `["acme.com"]`). Used for domain-based SSO lookup. |
| `attribute_mapping` | No | Map SAML attributes to user claims (see [Attribute mapping](#attribute-mapping)) |
| `name_id_format` | No | Request a specific NameID format: `persistent`, `emailAddress`, `transient`, or `unspecified` |
| `resource_id` | No | A custom external identifier for the provider |
| `disabled` | No | Set to `true` to register but disable the provider |
{/* supa-mdx-lint-enable Rule003Spelling */}
| Parameter | Required | Description |
| ------------------- | ------------ | --------------------------------------------------------------------------------------------- |
| `type` | Yes | Must be `"saml"` |
| `metadata_url` | One of these | HTTPS URL to the IdP's SAML metadata (auto-refreshed) |
| `metadata_xml` | One of these | Raw IdP metadata XML string |
| `domains` | No | Array of email domains to associate (e.g., `["acme.com"]`). Used for domain-based SSO lookup. |
| `attribute_mapping` | No | Map SAML attributes to user claims (see [Attribute mapping](#attribute-mapping)) |
| `name_id_format` | No | Request a specific NameID format: `persistent`, `emailAddress`, `transient`, or `unspecified` |
| `resource_id` | No | A custom external identifier for the provider |
| `disabled` | No | Set to `true` to register but disable the provider |
## Step 8: Configure your identity provider
On the IdP side, create a new SAML application and configure it with your SP details:
{/* supa-mdx-lint-disable Rule003Spelling */}
| IdP setting | Value |
|---|---|
| SP Entity ID / Audience | `{API_EXTERNAL_URL}/sso/saml/metadata` |
| ACS URL / Reply URL | `{API_EXTERNAL_URL}/sso/saml/acs` |
| NameID format | `persistent` (recommended) or `emailAddress` |
| Signing certificate | Upload from the SP metadata XML or provide the metadata URL |
{/* supa-mdx-lint-enable Rule003Spelling */}
| IdP setting | Value |
| ----------------------- | ----------------------------------------------------------- |
| SP Entity ID / Audience | `{API_EXTERNAL_URL}/sso/saml/metadata` |
| ACS URL / Reply URL | `{API_EXTERNAL_URL}/sso/saml/acs` |
| NameID format | `persistent` (recommended) or `emailAddress` |
| Signing certificate | Upload from the SP metadata XML or provide the metadata URL |
### IdP-specific configuration
@@ -262,14 +253,12 @@ On the IdP side, create a new SAML application and configure it with your SP det
<TabPanel id="okta" label="Okta">
**Okta setup:**
{/* supa-mdx-lint-disable Rule003Spelling */}
- Create a "SAML 2.0" application
- Single Sign-On URL: `{API_EXTERNAL_URL}/sso/saml/acs`
- Audience URI (SP Entity ID): `{API_EXTERNAL_URL}/sso/saml/metadata`
- Default RelayState: leave blank
- Name ID format: `Persistent`
{/* supa-mdx-lint-enable Rule003Spelling */}
</TabPanel>
@@ -318,21 +307,17 @@ On the IdP side, create a new SAML application and configure it with your SP det
Attribute mapping lets you control how SAML assertion attributes are translated into Supabase user claims. If no mapping is provided, Auth uses sensible defaults:
**Default email detection order:**
{/* supa-mdx-lint-disable Rule003Spelling */}
1. `urn:oid:0.9.2342.19200300.100.1.3` (LDAP mail OID)
2. `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
3. `http://schemas.xmlsoap.org/claims/EmailAddress`
4. Attributes named `mail`, `Mail`, or `email`
5. Subject NameID (if it looks like an email address)
{/* supa-mdx-lint-enable Rule003Spelling */}
**Default user ID detection:**
{/* supa-mdx-lint-disable Rule003Spelling */}
1. `urn:oasis:names:tc:SAML:attribute:subject-id` attribute
2. Subject NameID (if format is `persistent`)
{/* supa-mdx-lint-enable Rule003Spelling */}
### Custom attribute mapping example
@@ -521,15 +506,13 @@ The response should include `app_metadata.provider: "sso:saml"` and any mapped a
## Environment variable reference
{/* supa-mdx-lint-disable Rule003Spelling */}
| Variable | Default | Description |
|---|---|---|
| `SAML_ENABLED` | `false` | Enable the SAML SSO engine |
| `SAML_PRIVATE_KEY` | - | Base64-encoded PKCS#1 RSA private key (min 2048-bit). Used to sign SAML requests and optionally decrypt assertions. |
| `SAML_ALLOW_ENCRYPTED_ASSERTIONS` | `false` | Accept encrypted SAML assertions from IdPs |
| `SAML_RELAY_STATE_VALIDITY_PERIOD` | `2m0s` | How long relay state tokens remain valid. Increase if users on slow networks time out during the IdP redirect. |
| `SAML_RATE_LIMIT_ASSERTION` | `15` | Maximum ACS requests per second. Protects against assertion replay floods. |
{/* supa-mdx-lint-enable Rule003Spelling */}
| Variable | Default | Description |
| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `SAML_ENABLED` | `false` | Enable the SAML SSO engine |
| `SAML_PRIVATE_KEY` | - | Base64-encoded PKCS#1 RSA private key (min 2048-bit). Used to sign SAML requests and optionally decrypt assertions. |
| `SAML_ALLOW_ENCRYPTED_ASSERTIONS` | `false` | Accept encrypted SAML assertions from IdPs |
| `SAML_RELAY_STATE_VALIDITY_PERIOD` | `2m0s` | How long relay state tokens remain valid. Increase if users on slow networks time out during the IdP redirect. |
| `SAML_RATE_LIMIT_ASSERTION` | `15` | Maximum ACS requests per second. Protects against assertion replay floods. |
## Troubleshooting
@@ -576,8 +559,6 @@ base64 -w 0 -i pk_rsa1.der
### User is created but attributes are missing
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- Check your `attribute_mapping` configuration. Use the IdP's SAML assertion viewer (most IdPs have one) to see the exact attribute names being sent.
- Attribute names are matched case-insensitively against both the `Name` and `FriendlyName` fields in the assertion.
- Mapped attributes appear in `user.user_metadata`.
@@ -24,8 +24,6 @@ The most commonly used endpoints are implemented, and more will be added. Implem
### Bucket operations
{/* supa-mdx-lint-disable Rule003Spelling */}
| API Name | Feature |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ✅ [ListBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) | |
@@ -40,12 +38,8 @@ The most commonly used endpoints are implemented, and more will be added. Implem
| ❌ [PutBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html) | ❌ Checksums:<br/> ❌ x-amz-sdk-checksum-algorithm<br/> ❌ x-amz-checksum-algorithm<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner |
| ❌ [PutBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html) | ❌ Checksums:<br/> ❌ x-amz-sdk-checksum-algorithm<br/> ❌ x-amz-checksum-algorithm<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner |
{/* supa-mdx-lint-enable Rule003Spelling */}
### Object operations
{/* supa-mdx-lint-disable Rule003Spelling */}
| API Name | Feature |
| -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ✅ [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) | ✅ Conditional Operations:<br/> ✅ If-Match<br/> ✅ If-Modified-Since<br/> ✅ If-None-Match<br/> ✅ If-Unmodified-Since<br/>✅ Range:<br/> ✅ Range (has no effect in HeadObject)<br/> ✅ partNumber<br/>❌ SSE-C:<br/> ❌ x-amz-server-side-encryption-customer-algorithm<br/> ❌ x-amz-server-side-encryption-customer-key<br/> ❌ x-amz-server-side-encryption-customer-key-MD5<br/>❌ Request Payer:<br/> ❌ x-amz-request-payer<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner |
@@ -63,5 +57,3 @@ The most commonly used endpoints are implemented, and more will be added. Implem
| ✅ [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) | ✅ System Metadata:<br/>❌ Content-MD5<br/>❌ SSE-C:<br/> ❌ x-amz-server-side-encryption<br/> ❌ x-amz-server-side-encryption-customer-algorithm<br/> ❌ x-amz-server-side-encryption-customer-key<br/> ❌ x-amz-server-side-encryption-customer-key-MD5<br/>❌ Request Payer:<br/> ❌ x-amz-request-payer<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner |
| ✅ [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) | ❌ Conditional Operations:<br/> ❌ x-amz-copy-source<br/> ❌ x-amz-copy-source-if-match<br/> ❌ x-amz-copy-source-if-modified-since<br/> ❌ x-amz-copy-source-if-none-match<br/> ❌ x-amz-copy-source-if-unmodified-since<br/>✅ Range:<br/> ✅ x-amz-copy-source-range<br/>❌ SSE-C:<br/> ❌ x-amz-server-side-encryption-customer-algorithm<br/> ❌ x-amz-server-side-encryption-customer-key<br/> ❌ x-amz-server-side-encryption-customer-key-MD5<br/> ❌ x-amz-copy-source-server-side-encryption-customer-algorithm<br/> ❌ x-amz-copy-source-server-side-encryption-customer-key<br/> ❌ x-amz-copy-source-server-side-encryption-customer-key-MD5<br/>❌ Request Payer:<br/> ❌ x-amz-request-payer<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner<br/> ❌ x-amz-source-expected-bucket-owner |
| ✅ [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html) | Query Parameters:<br/> ✅ max-parts<br/> ✅ part-number-marker<br/>❌ Request Payer:<br/> ❌ x-amz-request-payer<br/>❌ Bucket Owner:<br/> ❌ x-amz-expected-bucket-owner |
{/* supa-mdx-lint-enable Rule003Spelling */}
@@ -110,8 +110,6 @@ However, you can also review the below **example cases** for an idea of possible
### Example cases
{/* supa-mdx-lint-disable Rule003Spelling */}
### TypeError: Undefined variables
A `TypeError` occurs when any JavaScript datatype is misused. For instance, trying to execute a number as if it were a function would cause the error:
@@ -170,8 +168,6 @@ finally {
}
```
{/* supa-mdx-lint-disable Rule003Spelling */}
### ReferenceError: Var is not defined
A `ReferenceError` occurs when one tries to reference a variable that does not exist in the code's scope. Often times caused by a typo or missing import.
@@ -224,8 +220,6 @@ catch (error) {
}
```
{/* supa-mdx-lint-disable Rule003Spelling */}
### SyntaxError: Special case - CORS violation
A `SyntaxError` error occurs when Deno's grammatical rules are violated, such as failing to close a parenthesis:
@@ -6,8 +6,6 @@ keywords = [ "channels", "useEffect", "react", "memory leak", "quota", "TooManyC
database_id = "dee93cc3-0ab1-4101-8ad4-31d8682c8844"
---
{/* supa-mdx-lint-disable Rule003Spelling */}
## What is the TooManyChannels error?
The TooManyChannels error occurs when your application tries to create more than the allowed number of Realtime channels. When you exceed this limit, you'll see an error with the code `ChannelRateLimitReached`.
@@ -16,21 +14,15 @@ This limit exists to protect both your application and Supabase servers from res
## What causes TooManyChannels errors?
{/* supa-mdx-lint-enable Rule003Spelling */}
The most common cause is accidentally creating channels without cleaning them up, especially in React applications. This happens when:
{/* supa-mdx-lint-disable Rule003Spelling */}
- Components create channels on every render without unsubscribing
- `useEffect` runs multiple times due to missing or incorrect dependencies
- Components unmount without cleaning up their channels
- Development mode in React (StrictMode) causes effects to run twice
{/* supa-mdx-lint-enable Rule003Spelling */}
Each time you call `supabase.channel('topic').subscribe()`, a new channel is created unless you properly clean it up.
{/* supa-mdx-lint-disable Rule003Spelling */}
Here's the most common mistake that might lead to TooManyChannels errors:
{/* supa-mdx-lint-enable Rule003Spelling */}
```tsx
// ❌ WRONG - Creates new channel on every render
@@ -64,8 +56,8 @@ Why this fails:
```tsx
// ✅ CORRECT - Properly manages channel lifecycle
import { useEffect } from 'react'
import { createClient } from '@supabase/supabase-js'
import { useEffect } from 'react'
// Create client outside component (singleton)
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
@@ -189,9 +181,7 @@ console.log(channel1 === channel2) // true
### 5. Handle strict mode in development
{/* supa-mdx-lint-disable Rule003Spelling */}
React StrictMode intentionally runs effects twice in development. Your cleanup function will handle this:
{/* supa-mdx-lint-enable Rule003Spelling */}
```tsx
// This works correctly even in StrictMode
@@ -206,8 +196,6 @@ useEffect(() => {
}, [])
```
{/* supa-mdx-lint-disable Rule003Spelling */}
### 6. Clean up on unmount for dynamic channels
If you create channels based on props:
@@ -195,7 +195,6 @@ Execution Time: 0.046 ms
[Stable functions do not seem to be honored in RLS in basic form](https://github.com/orgs/supabase/discussions/9311)
[current_setting can lead to bad performance when used on RLS](https://github.com/PostgREST/postgrest-docs/issues/609#)
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
Thanks Steve Chavez and Wolfgang Walther in those threads.
### Added example of security definer function having select of a team table, comparing against a column in main table
@@ -225,8 +224,6 @@ $$ language plpgsql security definer;
Some results:
{/* supa-mdx-lint-disable Rule003Spelling */}
| Policy | Index | Main Rs | Team Rs | on 10 teams | 100 | 500 | note |
| -------------------------------- | ----- | ------- | ------- | ----------- | ----- | ----- | ------------------ |
| =ANY(user_teams()) | no | 1M | 1000 | >2Min | >2Min | >2Min | TO or killed |
@@ -235,5 +232,3 @@ Some results:
| =ANY(ARRAY(select user_teams())) | yes | 1M | 1000 | 2ms | 3 | 3 | |
| in(1,2,3...100) | no | 1M | NA | 130ms | 142 | x | baseline check |
| =ANY(ARRAY(select user_teams())) | yes | 1M | 10K | x | x | x | 24ms (on 1K teams) |
{/* supa-mdx-lint-enable Rule003Spelling */}
@@ -24,8 +24,6 @@ Whatever the reason, here's how to rotate the keys for your Supabase project.
If you haven’t migrated to asymmetric JWT signing keys:
{/* supa-mdx-lint-disable Rule004ExcludeWords */}
We recommend that you migrate to asymmetric JWT signing keys and publishable/secret API keys as it is no longer possible to rotate the legacy anon, service and JWT secrets.
You can view this [**Get Started guide**](/docs/guides/auth/signing-keys#getting-started) for steps to migrate to asymmetric JWT signing keys.
@@ -111,7 +111,6 @@ This query:
**Example Output:**
| db_role | detected_user | error_severity | event_message | identifier |
| -------- | ------------- | -------------- | -------------------------------------------------------------------------------- | ---------- |
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
| postgres | support | LOG | statement: TRUNCATE TABLE public.data; -- source: dashboard -- user: f8c2e1a9... | ... |
You can further refine your search by filtering for specific commands like `TRUNCATE` or `DELETE` where `parsed.user_name = 'postgres'`.