mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix(docs): fix heading-order skips in guide and troubleshooting content (#48459)
Closes DOCS-1260 _See WAVE plugin no longer flags a jump in header hierarchy. Preview on left._ <img width="708" height="699" alt="Screenshot 2026-07-29 at 2 30 11 PM" src="https://github.com/user-attachments/assets/be5bf335-9e03-474f-8215-06fa505ab2db" /> ## Problem Beyond the 4 shared components fixed in [#48456](https://github.com/supabase/supabase/pull/48456), the [header hierarchy report](https://app.notion.com/p/supabase/Playwright-E2E-Triage-Reports-3ab5004b775f81e3bc60d058fa5a02c1) found plain content headings that skip a level. For example, you may see a `##` followed directly by an `####`. Jumps in headers breaks page navigation for screen reader users, who jump between headings expecting each level to nest one at a time. ## Solution Adjusted heading levels across the affected guide and troubleshooting pages so every section nests correctly, with no skipped levels. **Staging previews:** | Page | Preview | | --- | --- | | `/guides/api/rest/postgrest-error-codes` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/api/rest/postgrest-error-codes) | | `/guides/auth/oauth-server/getting-started` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/auth/oauth-server/getting-started) | | `/guides/database/custom-postgres-config` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/custom-postgres-config) | | `/guides/database/drizzle` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/drizzle) | | `/guides/database/extensions` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/extensions) | | `/guides/database/extensions/pgaudit` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/extensions/pgaudit) | | `/guides/database/postgres-js` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/postgres-js) | | `/guides/database/replication/manual-replication-monitoring` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/replication/manual-replication-monitoring) | | `/guides/database/replication/manual-replication-setup` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/replication/manual-replication-setup) | | `/guides/database/replication/pipelines-monitoring` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/database/replication/pipelines-monitoring) | | `/guides/functions/debugging-tools` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/debugging-tools) | | `/guides/functions/development-tips` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/development-tips) | | `/guides/functions/examples/auth-send-email-hook-react-email-resend` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/examples/auth-send-email-hook-react-email-resend) | | `/guides/functions/examples/image-manipulation` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/examples/image-manipulation) | | `/guides/functions/examples/semantic-search` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/examples/semantic-search) | | `/guides/functions/examples/send-emails` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/examples/send-emails) | | `/guides/functions/examples/sentry-monitoring` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/examples/sentry-monitoring) | | `/guides/functions/wasm` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/functions/wasm) | | `/guides/getting-started` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/getting-started) | | `/guides/platform/aws-marketplace` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/aws-marketplace) | | `/guides/platform/aws-marketplace/faq` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/aws-marketplace/faq) | | `/guides/platform/billing-faq` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/billing-faq) | | `/guides/platform/ipv4-address` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/ipv4-address) | | `/guides/platform/migrating-within-supabase/backup-restore` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/migrating-within-supabase/backup-restore) | | `/guides/platform/privatelink` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/platform/privatelink) | | `/guides/queues/api` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/queues/api) | | `/guides/resources` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/resources) | | `/guides/security/hipaa-compliance` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/security/hipaa-compliance) | | `/guides/security/security-testing` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/security/security-testing) | | `/guides/security/soc-2-compliance` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/security/soc-2-compliance) | | `/guides/self-hosting` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/self-hosting) | | `/guides/storage/cdn/fundamentals` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/cdn/fundamentals) | | `/guides/storage/debugging/logs` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/debugging/logs) | | `/guides/storage/production/scaling` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/production/scaling) | | `/guides/storage/schema/helper-functions` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/schema/helper-functions) | | `/guides/storage/serving/image-transformations` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/serving/image-transformations) | | `/guides/storage/uploads/resumable-uploads` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/storage/uploads/resumable-uploads) | | `/guides/troubleshooting/an-invalid-response-was-received-from-the-upstream-server-error-when-querying-auth-RI4Vl-` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/an-invalid-response-was-received-from-the-upstream-server-error-when-querying-auth-RI4Vl-) | | `/guides/troubleshooting/are-all-features-available-in-self-hosted-supabase-THPcqw` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/are-all-features-available-in-self-hosted-supabase-THPcqw) | | `/guides/troubleshooting/avoiding-timeouts-in-long-running-queries-6nmbdN` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/avoiding-timeouts-in-long-running-queries-6nmbdN) | | `/guides/troubleshooting/database-api-42501-errors` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/database-api-42501-errors) | | `/guides/troubleshooting/disabling-prepared-statements-qL8lEL` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/disabling-prepared-statements-qL8lEL) | | `/guides/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/discovering-and-interpreting-api-errors-in-the-logs-7xREI9) | | `/guides/troubleshooting/edge-function-504-error-response` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/edge-function-504-error-response) | | `/guides/troubleshooting/high-cpu-and-slow-queries-with-error-must-be-a-superuser-to-terminate-superuser-process` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/high-cpu-and-slow-queries-with-error-must-be-a-superuser-to-terminate-superuser-process) | | `/guides/troubleshooting/how-postgres-chooses-which-index-to-use-_JHrf4` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/how-postgres-chooses-which-index-to-use-_JHrf4) | | `/guides/troubleshooting/how-to-change-max-database-connections-_BQ8P5` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/how-to-change-max-database-connections-_BQ8P5) | | `/guides/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/how-to-interpret-and-explore-the-postgres-logs-OuCIOj) | | `/guides/troubleshooting/how-to-migrate-from-supabase-auth-helpers-to-ssr-package-5NRunM` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/how-to-migrate-from-supabase-auth-helpers-to-ssr-package-5NRunM) | | `/guides/troubleshooting/http-api-issues` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/http-api-issues) | | `/guides/troubleshooting/increase-vector-lookup-speeds-by-applying-an-hsnw-index-ohLHUM` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/increase-vector-lookup-speeds-by-applying-an-hsnw-index-ohLHUM) | | `/guides/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/interpreting-supabase-grafana-cpu-charts-9JSlkC) | | `/guides/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/interpreting-supabase-grafana-io-charts-MUynDR) | | `/guides/troubleshooting/new-branch-doesnt-copy-database` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/new-branch-doesnt-copy-database) | | `/guides/troubleshooting/not-receiving-auth-emails-from-the-supabase-project-OFSNzw` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/not-receiving-auth-emails-from-the-supabase-project-OFSNzw) | | `/guides/troubleshooting/resolving-500-status-authentication-errors-7bU5U8` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/resolving-500-status-authentication-errors-7bU5U8) | | `/guides/troubleshooting/resolving-cannot-execute-update-in-a-read-only-transaction-on-transaction-pooler-connections-ef582c` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/resolving-cannot-execute-update-in-a-read-only-transaction-on-transaction-pooler-connections-ef582c) | | `/guides/troubleshooting/resolving-database-hostname-and-managing-your-ip-address-pVlwE0` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/resolving-database-hostname-and-managing-your-ip-address-pVlwE0) | | `/guides/troubleshooting/rls-simplified-BJTcS8` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/rls-simplified-BJTcS8) | | `/guides/troubleshooting/security-of-anonymous-sign-ins-iOrGCL` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/security-of-anonymous-sign-ins-iOrGCL) | | `/guides/troubleshooting/supabase--your-network-ipv4-and-ipv6-compatibility-cHe3BP` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/supabase--your-network-ipv4-and-ipv6-compatibility-cHe3BP) | | `/guides/troubleshooting/supabase-grafana-memory-charts` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/supabase-grafana-memory-charts) | | `/guides/troubleshooting/supavisor-faq-YyP5tI` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/supavisor-faq-YyP5tI) | | `/guides/troubleshooting/tracking-postgres-role-activity-to-specific-dashboard-users-8d3715` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/tracking-postgres-role-activity-to-specific-dashboard-users-8d3715) | | `/guides/troubleshooting/transferring-from-cloud-to-self-host-in-supabase-2oWNvW` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/transferring-from-cloud-to-self-host-in-supabase-2oWNvW) | | `/guides/troubleshooting/understanding-postgresql-explain-output-Un9dqX` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/understanding-postgresql-explain-output-Un9dqX) | | `/guides/troubleshooting/understanding-postgresql-logging-levels-and-how-they-impact-your-project-KXiJRm` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/understanding-postgresql-logging-levels-and-how-they-impact-your-project-KXiJRm) | | `/guides/troubleshooting/vercel-integration-environment-variables-not-syncing-for-persistent-git-branches-b9191e` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/vercel-integration-environment-variables-not-syncing-for-persistent-git-branches-b9191e) | | `/guides/troubleshooting/why-are-there-gaps-in-my-postgres-id-sequence-Frifus` | [Preview](https://docs-git-docs-heading-hierarchy-supabase.vercel.app/docs/guides/troubleshooting/why-are-there-gaps-in-my-postgres-id-sequence-Frifus) | ## Manual testing 1. See affected pages. Recommend running a browser plugin like WAVE and selecting the **Structure** tab. 2. See the headings do not skip. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Documentation** * Standardized heading hierarchy across many guides and troubleshooting articles to improve readability and navigation. * Updated several documentation link targets to the correct new locations. * Reformatted multiple sections (including replication monitoring, Edge Functions, Storage, authentication, security, and networking) without changing instructions. * Queue Data API docs were restructured via heading-level adjustments (no operational changes). * Billing FAQ received clearer, more detailed payment-failure and tax guidance, plus related link updates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e241a21a9a
commit
81523d5d8c
69 files changed
+348
-342
No files matched your search
@@ -147,7 +147,7 @@ Data API error unspecified
|
||||
|
||||
One can filter for API errors in the [log explorer](/dashboard/project/_/logs/explorer). Below are useful queries for filtering and analyzing API errors:
|
||||
|
||||
#### Find all API errors that occurred at the database level
|
||||
### Find all API errors that occurred at the database level
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -171,7 +171,7 @@ order by timestamp desc
|
||||
limit 100;
|
||||
```
|
||||
|
||||
#### Find specific database error from the data API
|
||||
### Find specific database error from the data API
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -199,7 +199,7 @@ PostgREST error codes are only captured in the logs for projects running V14+. Y
|
||||
|
||||
</Admonition>
|
||||
|
||||
#### Find specific API error
|
||||
### Find specific API error
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -219,7 +219,7 @@ where
|
||||
and regexp_contains(proxy_status, '(?i)THE_RELEVANT_STATUS_CODE');
|
||||
```
|
||||
|
||||
#### Count errors per path by hour:
|
||||
### Count errors per path by hour:
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -241,7 +241,7 @@ where status_code >= 300 and regexp_contains(path, '^/rest/v1/')
|
||||
group by hour, proxy_status, path;
|
||||
```
|
||||
|
||||
#### Find data API request from specific authenticated user
|
||||
### Find data API request from specific authenticated user
|
||||
|
||||
```sql
|
||||
select
|
||||
|
||||
@@ -498,7 +498,7 @@ Store the client secret securely. It will only be shown once. If you lose it, yo
|
||||
|
||||
</Admonition>
|
||||
|
||||
#### Token endpoint authentication method
|
||||
### Token endpoint authentication method
|
||||
|
||||
When a client exchanges an authorization code or refreshes a token, it must authenticate with the token endpoint. The `token_endpoint_auth_method` controls how this authentication happens:
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Customizing Postgres configurations provides _advanced_ control over your databa
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Viewing settings
|
||||
## Viewing settings
|
||||
|
||||
To list all Postgres settings and their descriptions, run:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ breadcrumb: 'ORM Quickstarts'
|
||||
hideToc: true
|
||||
---
|
||||
|
||||
### Connecting with Drizzle
|
||||
## Connecting with Drizzle
|
||||
|
||||
[Drizzle ORM](https://github.com/drizzle-team/drizzle-orm) is a TypeScript ORM for SQL databases designed with maximum type safety in mind. You can use their ORM to connect to your database.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ description: 'Using Postgres extensions.'
|
||||
Extensions are exactly as they sound - they "extend" the database with functionality which isn't part of the Postgres core.
|
||||
Supabase has pre-installed some of the most useful open source extensions.
|
||||
|
||||
### Enable and disable extensions
|
||||
## Enable and disable extensions
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
@@ -54,11 +54,11 @@ In addition to the pre-configured extensions, you can also install your own SQL
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Upgrade extensions
|
||||
## Upgrade extensions
|
||||
|
||||
If a new version of an extension becomes available on Supabase, you need to initiate a software upgrade in the [Infrastructure Settings](/dashboard/project/_/settings/infrastructure) to access it. Software upgrades can also be initiated by restarting your server in the [General Settings](/dashboard/project/_/settings/general).
|
||||
|
||||
### Full list of extensions
|
||||
## Full list of extensions
|
||||
|
||||
Supabase is pre-configured with over 50 extensions and you can install additional extensions through the [database.dev](https://database.dev/) package manager.
|
||||
|
||||
|
||||
@@ -345,15 +345,15 @@ To prevent PGAudit from monitoring the problematic roles, you'll want to change
|
||||
|
||||
## FAQ
|
||||
|
||||
#### Using PGAudit to debug database functions
|
||||
### Using PGAudit to debug database functions
|
||||
|
||||
Technically yes, but it is not the best approach. It is better to check out our [function debugging guide](/docs/guides/database/functions#general-logging) instead.
|
||||
|
||||
#### Downloading database logs
|
||||
### Downloading database logs
|
||||
|
||||
In the [Logs Dashboard](/dashboard/project/_/logs/postgres-logs) you can download logs as CSVs.
|
||||
|
||||
#### Logging observed table rows
|
||||
### Logging observed table rows
|
||||
|
||||
By default, PGAudit records queries, but not the returned rows. You can modify this behavior with the `pgaudit.log_rows` variable:
|
||||
|
||||
@@ -367,13 +367,13 @@ alter role "postgres" set pgaudit.log_rows to 'off';
|
||||
|
||||
You should not do this unless you are _absolutely_ certain it is necessary for your use case. It can expose sensitive values to your logs that ideally should not be preserved. Furthermore, if done in excess, it can noticeably reduce database performance.
|
||||
|
||||
#### Logging function parameters
|
||||
### Logging function parameters
|
||||
|
||||
We don't currently support configuring `pgaudit.log_parameter` because it may log secrets in encrypted columns if you are using [pgsodium](/docs/guides/database/extensions/pgsodium) or[Vault](/docs/guides/database/vault).
|
||||
|
||||
You can upvote this [feature request](https://github.com/orgs/supabase/discussions/20183) with your use-case if you'd like this restriction lifted.
|
||||
|
||||
#### Does PGAudit support system wide configurations?
|
||||
### Does PGAudit support system wide configurations?
|
||||
|
||||
PGAudit allows settings to be applied to 3 different database scopes:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ breadcrumb: 'ORM Quickstarts'
|
||||
hideToc: true
|
||||
---
|
||||
|
||||
### Connecting with Postgres.js
|
||||
## Connecting with Postgres.js
|
||||
|
||||
[Postgres.js](https://github.com/porsager/postgres) is a full-featured Postgres client for Node.js and Deno.
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ Monitoring replication lag is important and there are 3 ways to do this:
|
||||
- pg_stat_replication_replay_lag - lag to replay WAL files from the source DB on the target DB (throttled by disk or high activity)
|
||||
- pg_stat_replication_send_lag - lag in sending WAL files from the source DB (a high lag means that the publisher is not being asked to send new WAL files OR network issues)
|
||||
|
||||
### Primary
|
||||
## Primary
|
||||
|
||||
#### Replication status and lag
|
||||
### Replication status and lag
|
||||
|
||||
The `pg_stat_replication` table shows the status of any replicas connected to the primary database.
|
||||
|
||||
@@ -29,7 +29,7 @@ select pid, application_name, state, sent_lsn, write_lsn, flush_lsn, replay_lsn,
|
||||
from pg_stat_replication;
|
||||
```
|
||||
|
||||
#### Replication slot status
|
||||
### Replication slot status
|
||||
|
||||
A replication slot can be in one of three states:
|
||||
|
||||
@@ -43,7 +43,7 @@ The state can be checked using the `pg_replication_slots` table:
|
||||
select slot_name, active, state from pg_replication_slots;
|
||||
```
|
||||
|
||||
#### WAL size
|
||||
### WAL size
|
||||
|
||||
The WAL size can be checked using the `pg_ls_waldir()` function:
|
||||
|
||||
@@ -51,15 +51,15 @@ The WAL size can be checked using the `pg_ls_waldir()` function:
|
||||
select * from pg_ls_waldir();
|
||||
```
|
||||
|
||||
#### Check the LSN
|
||||
### Check the LSN
|
||||
|
||||
```sql
|
||||
select pg_current_wal_lsn();
|
||||
```
|
||||
|
||||
### Subscriber
|
||||
## Subscriber
|
||||
|
||||
#### Subscription status
|
||||
### Subscription status
|
||||
|
||||
The `pg_subscription` table shows the status of any subscriptions on a replica and the `pg_subscription_rel` table shows the status of each table within a subscription.
|
||||
|
||||
@@ -91,7 +91,7 @@ ORDER BY
|
||||
table_name;
|
||||
```
|
||||
|
||||
#### Check the LSN
|
||||
### Check the LSN
|
||||
|
||||
```sql
|
||||
select pg_last_wal_replay_lsn();
|
||||
|
||||
@@ -14,7 +14,7 @@ This guide is for replicating data to destination systems using your own tools.
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
To set up replication, the following is recommended:
|
||||
|
||||
|
||||
@@ -10,14 +10,14 @@ sidebar_label: 'Monitoring'
|
||||
|
||||
After setting up Supabase Pipelines, you can monitor the status and health of your pipelines directly from the Dashboard. A pipeline first performs an initial sync of existing rows, then uses ongoing replication (CDC) to send subsequent database changes to your destination.
|
||||
|
||||
### Viewing pipeline status
|
||||
## Viewing pipeline status
|
||||
|
||||
To monitor your pipelines:
|
||||
|
||||
1. Navigate to the [**Database > Replication**](/dashboard/project/_/database/replication) section of the Dashboard
|
||||
2. You'll see a list of all your destinations with their pipeline status
|
||||
|
||||
#### Pipeline states
|
||||
### Pipeline states
|
||||
|
||||
Each destination shows its pipeline in one of these states:
|
||||
|
||||
@@ -31,7 +31,7 @@ Each destination shows its pipeline in one of these states:
|
||||
| **Failed** | Pipeline has encountered an error (hover over the status to view error details) |
|
||||
| **Unknown** | The Dashboard can't currently determine the pipeline status |
|
||||
|
||||
### Viewing detailed pipeline metrics
|
||||
## Viewing detailed pipeline metrics
|
||||
|
||||
For detailed information about a specific pipeline, click **View pipeline** on the destination. This opens the pipeline status page where you can monitor replication performance and table states.
|
||||
|
||||
@@ -44,7 +44,7 @@ For detailed information about a specific pipeline, click **View pipeline** on t
|
||||
zoomable
|
||||
/>
|
||||
|
||||
#### Replication lag metrics
|
||||
### Replication lag metrics
|
||||
|
||||
The status page shows replication lag metrics that help you determine how far the pipeline is behind Postgres. These metrics are loaded directly from Postgres replication slot state.
|
||||
|
||||
@@ -64,7 +64,7 @@ Pipelines uses one main pipeline replication slot for ongoing replication. Durin
|
||||
|
||||
Temporary table-sync slots show the same kind of lag and slot health metrics while they are active. After a table finishes its initial sync and catches up, its temporary slot is removed and ongoing replication continues through the main pipeline slot. For overall replication health, focus first on the main pipeline slot.
|
||||
|
||||
#### Slot statuses
|
||||
### Slot statuses
|
||||
|
||||
Replication slot status tells you whether Postgres is still retaining the WAL that the pipeline needs to continue from its current position.
|
||||
|
||||
@@ -76,7 +76,7 @@ Replication slot status tells you whether Postgres is still retaining the WAL th
|
||||
| **Lost** | Broken. Some WAL files this pipeline's replication slot needs have already been removed. The pipeline can no longer continue from this slot. Recreate the pipeline, or set **Invalidated slot behavior** to **Recreate** in the pipeline's advanced settings and restart it. |
|
||||
| **Unknown** | Postgres reported an unknown or unavailable state for this pipeline's replication slot. |
|
||||
|
||||
#### Table states
|
||||
### Table states
|
||||
|
||||
The pipeline status page also shows the state of individual tables being replicated. Each table can be in one of these states:
|
||||
|
||||
@@ -91,7 +91,7 @@ The pipeline status page also shows the state of individual tables being replica
|
||||
| **Not Available** | Table state is temporarily unavailable while the pipeline changes state |
|
||||
| **Unknown** | The Dashboard received a table state it doesn't recognize |
|
||||
|
||||
### Dealing with replication lag
|
||||
## Dealing with replication lag
|
||||
|
||||
Replication lag means the pipeline is behind the source database. Some lag is expected during the initial sync, after a burst of writes, or after restarting a stopped pipeline. Lag becomes a problem when it keeps increasing, when **WAL retention remaining** is running low, or when the slot status moves to **Unreserved** or **Lost**.
|
||||
|
||||
@@ -104,7 +104,7 @@ Lag can come from several places:
|
||||
- **Stopped or disconnected pipeline**: When a pipeline is stopped, disconnected, or failed, Postgres keeps WAL for the slot until the retention limit is reached.
|
||||
- **Slow initial sync**: A temporary table-sync slot can fall behind if existing rows are copied more slowly than new changes are written to that table.
|
||||
|
||||
#### Initial sync and table-sync slots
|
||||
### Initial sync and table-sync slots
|
||||
|
||||
A common initial sync issue happens when a large or busy table is still in **Copying** while new rows keep being inserted or updated. The temporary table-sync slot retains changes that happen during the initial sync. If copying is too slow compared to the table's write rate, the slot can move to **Unreserved** and then **Lost** if Postgres removes changes the sync still needs.
|
||||
|
||||
@@ -116,7 +116,7 @@ When a table-sync slot is lost, the affected table needs to run its initial sync
|
||||
|
||||
After the affected table finishes copying and catches up, the temporary slot is deleted. The table then continues through the main pipeline replication slot.
|
||||
|
||||
#### Investigate the lag
|
||||
### Investigate the lag
|
||||
|
||||
1. Open [**Database > Replication**](/dashboard/project/_/database/replication) and check the destination's lag column.
|
||||
2. Click **View pipeline** and check **Waiting to sync**, **WAL retention remaining**, **Last check-in**, **Connected**, and **Slot status**.
|
||||
@@ -124,7 +124,7 @@ After the affected table finishes copying and catches up, the temporary slot is
|
||||
4. Open [**Logs > Replication**](/dashboard/project/_/logs/replication-logs) and look for destination errors, retries, rate limits, schema errors, or repeated restarts.
|
||||
5. Compare the lag trend with recent database activity, such as imports, migrations, bulk updates, or long transactions.
|
||||
|
||||
#### Respond based on the slot status
|
||||
### Respond based on the slot status
|
||||
|
||||
| Slot status | What to do |
|
||||
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -134,7 +134,7 @@ After the affected table finishes copying and catches up, the temporary slot is
|
||||
| **Lost** | The pipeline cannot continue from the existing slot because required WAL has been removed. Recreate the pipeline, or set **Invalidated slot behavior** to **Recreate** in the pipeline's advanced settings and restart the pipeline. This creates a new slot and starts replication from scratch for all tables. |
|
||||
| **Unknown** | Check replication logs for errors or missing slot details. If the status remains unknown while the pipeline should be running, contact support with the pipeline ID and recent log details. |
|
||||
|
||||
#### Reduce future lag risk
|
||||
### Reduce future lag risk
|
||||
|
||||
- Keep publications focused on the tables and operations you need at the destination.
|
||||
- Avoid leaving pipelines stopped for long periods while the source database is still receiving writes.
|
||||
@@ -142,11 +142,11 @@ After the affected table finishes copying and catches up, the temporary slot is
|
||||
- For BigQuery, verify that service account permissions, table requirements, and replica identity settings match the [BigQuery destination guide](/docs/guides/database/replication/bigquery).
|
||||
- If the initial sync is the bottleneck, review **Table sync workers** and **Copy connections per table** in the pipeline's advanced settings. Increasing either can use more source database connections; increasing table sync workers can also use more temporary replication slots.
|
||||
|
||||
### Handling errors
|
||||
## Handling errors
|
||||
|
||||
Errors can occur at two levels: per table or per pipeline.
|
||||
|
||||
#### Table errors
|
||||
### Table errors
|
||||
|
||||
Table errors occur during the initial sync and affect individual tables. These errors can be retried without stopping the entire pipeline.
|
||||
|
||||
@@ -160,7 +160,7 @@ Table errors occur during the initial sync and affect individual tables. These e
|
||||
|
||||
When a table encounters an error during the initial sync, you can reset the table state. This restarts that table's initial sync from the beginning.
|
||||
|
||||
#### Pipeline errors
|
||||
### Pipeline errors
|
||||
|
||||
Pipeline errors can occur during startup or ongoing replication and affect the entire pipeline. If a non-retryable pipeline-level error occurs, the entire pipeline stops and enters a **Failed** state instead of silently skipping the failure.
|
||||
|
||||
@@ -178,7 +178,7 @@ To recover from a pipeline error, you'll need to:
|
||||
2. Fix the underlying issue (e.g., destination connectivity, schema compatibility)
|
||||
3. Restart the pipeline from the destinations list
|
||||
|
||||
### Viewing logs
|
||||
## Viewing logs
|
||||
|
||||
To see detailed logs for all your pipelines:
|
||||
|
||||
@@ -192,16 +192,16 @@ Logs contain diagnostic information that may be too technical for most users. If
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Common monitoring scenarios
|
||||
## Common monitoring scenarios
|
||||
|
||||
#### Checking if replication is healthy
|
||||
### Checking if replication is healthy
|
||||
|
||||
1. Navigate to the [**Database > Replication**](/dashboard/project/_/database/replication) section of the Dashboard
|
||||
2. Verify your destination shows a "Running" status
|
||||
3. Click **View pipeline** to check replication lag and table states
|
||||
4. Ensure all tables show a "Live" state
|
||||
|
||||
#### Investigating errors
|
||||
### Investigating errors
|
||||
|
||||
If you see a **Failed** status:
|
||||
|
||||
@@ -211,7 +211,7 @@ If you see a **Failed** status:
|
||||
4. Navigate to the [**Logs > Replication**](/dashboard/project/_/logs/replication-logs) section of the Dashboard for full error details
|
||||
5. For table errors, attempt to reset the affected tables
|
||||
|
||||
#### Monitoring performance
|
||||
### Monitoring performance
|
||||
|
||||
To ensure optimal performance:
|
||||
|
||||
@@ -220,7 +220,7 @@ To ensure optimal performance:
|
||||
3. Review logs for warnings or performance issues
|
||||
4. If lag is consistently high, review your publication and destination configuration
|
||||
|
||||
### Troubleshooting
|
||||
## Troubleshooting
|
||||
|
||||
If you notice issues with your replication:
|
||||
|
||||
@@ -232,7 +232,7 @@ If you notice issues with your replication:
|
||||
|
||||
For more troubleshooting tips, see the [Pipelines FAQ](/docs/guides/database/replication/pipelines-faq).
|
||||
|
||||
### Next steps
|
||||
## Next steps
|
||||
|
||||
- [Set up Pipelines](/docs/guides/database/replication/pipelines)
|
||||
- [View the Pipelines FAQ](/docs/guides/database/replication/pipelines-faq)
|
||||
@@ -8,7 +8,7 @@ tocVideo: 'sOrtcoKg5zQ'
|
||||
|
||||
Since [v1.171.0](https://github.com/supabase/cli/releases/tag/v1.171.0) the Supabase CLI supports debugging Edge Functions via the v8 inspector protocol, allowing for debugging via [Chrome DevTools](https://developer.chrome.com/docs/devtools/) and other Chromium-based browsers.
|
||||
|
||||
### Inspect with Chrome Developer Tools
|
||||
## Inspect with Chrome Developer Tools
|
||||
|
||||
1. Serve your functions in inspect mode. This will set a breakpoint at the first line to pause script execution before any code runs.
|
||||
```bash
|
||||
|
||||
@@ -7,7 +7,7 @@ subtitle: 'Tips for getting started with Edge Functions.'
|
||||
|
||||
Here are a few recommendations when you first start developing Edge Functions.
|
||||
|
||||
### Using HTTP methods
|
||||
## Using HTTP methods
|
||||
|
||||
Edge Functions support `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and `OPTIONS`. A Function can be designed to perform different actions based on a request's HTTP method. See the [example on building a RESTful service](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/restful-tasks) to learn how to handle different HTTP methods in your Function.
|
||||
|
||||
@@ -17,11 +17,11 @@ HTML content is not supported. `GET` requests that return `text/html` will be re
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Naming Edge Functions
|
||||
## Naming Edge Functions
|
||||
|
||||
We recommend using hyphens to name functions because hyphens are the most URL-friendly of all the naming conventions (snake_case, camelCase, PascalCase).
|
||||
|
||||
### Organizing your Edge Functions
|
||||
## Organizing your Edge Functions
|
||||
|
||||
We recommend developing "fat functions". This means that you should develop few large functions, rather than many small functions. One common pattern when developing Functions is that you need to share code between two or more Functions. To do this, you can store any shared code in a folder prefixed with an underscore (`_`). We also recommend a separate folder for [Unit Tests](/docs/guides/functions/unit-test) including the name of the function followed by a `-test` suffix.
|
||||
We recommend this folder structure:
|
||||
@@ -45,7 +45,7 @@ We recommend this folder structure:
|
||||
└── config.toml
|
||||
```
|
||||
|
||||
### Using config.toml
|
||||
## Using config.toml
|
||||
|
||||
Individual function configuration like [JWT verification](/docs/guides/local-development/cli/config#functions.function_name.verify_jwt) and [import map location](/docs/guides/local-development/cli/config#functions.function_name.import_map) can be set via the `config.toml` file.
|
||||
|
||||
@@ -55,7 +55,7 @@ verify_jwt = false
|
||||
import_map = './import_map.json'
|
||||
```
|
||||
|
||||
### Not using TypeScript
|
||||
## Not using TypeScript
|
||||
|
||||
When you create a new Edge Function, it will use TypeScript by default. However, it is possible to write and deploy Edge Functions using pure JavaScript.
|
||||
|
||||
@@ -75,12 +75,12 @@ entrypoint = './functions/hello-world/index.js' # path must be relative to confi
|
||||
|
||||
You can use any `.ts`, `.js`, `.tsx`, `.jsx` or `.mjs` file as the `entrypoint` for a Function.
|
||||
|
||||
### Error handling
|
||||
## Error handling
|
||||
|
||||
The `supabase-js` library provides several error types that you can use to handle errors that might occur when invoking Edge Functions:
|
||||
|
||||
```js
|
||||
import { FunctionsHttpError, FunctionsRelayError, FunctionsFetchError } from '@supabase/supabase-js'
|
||||
import { FunctionsFetchError, FunctionsHttpError, FunctionsRelayError } from '@supabase/supabase-js'
|
||||
|
||||
const { data, error } = await supabase.functions.invoke('hello', {
|
||||
headers: { 'my-custom-header': 'my-custom-header-value' },
|
||||
@@ -97,7 +97,7 @@ if (error instanceof FunctionsHttpError) {
|
||||
}
|
||||
```
|
||||
|
||||
### Database Functions vs Edge Functions
|
||||
## Database Functions vs Edge Functions
|
||||
|
||||
For data-intensive operations we recommend using [Database Functions](/docs/guides/database/functions), which are executed within your database and can be called remotely using the [REST and GraphQL API](/docs/guides/api).
|
||||
|
||||
|
||||
+7
-7
@@ -12,7 +12,7 @@ Prefer to jump straight to the code? [Check out the example on GitHub](https://g
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
To get the most out of this guide, you’ll need to:
|
||||
|
||||
@@ -21,7 +21,7 @@ To get the most out of this guide, you’ll need to:
|
||||
|
||||
Make sure you have the latest version of the [Supabase CLI](/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) installed.
|
||||
|
||||
### 1. Create Supabase function
|
||||
## 1. Create Supabase function
|
||||
|
||||
Create a new function locally:
|
||||
|
||||
@@ -29,16 +29,16 @@ Create a new function locally:
|
||||
supabase functions new send-email
|
||||
```
|
||||
|
||||
### 2. Edit the handler function
|
||||
## 2. Edit the handler function
|
||||
|
||||
Paste the following code into the `index.ts` file:
|
||||
|
||||
```tsx supabase/functions/send-email/index.ts
|
||||
import { Webhook } from 'npm:standardwebhooks@^1'
|
||||
import { renderAsync } from 'npm:@react-email/components@^1'
|
||||
import { withSupabase } from 'npm:@supabase/server@^1'
|
||||
import React from 'npm:react@^19'
|
||||
import { Resend } from 'npm:resend@^6'
|
||||
import { Webhook } from 'npm:standardwebhooks@^1'
|
||||
|
||||
import { MagicLinkEmail } from './_templates/magic-link.tsx'
|
||||
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Create React Email templates
|
||||
## 3. Create React Email templates
|
||||
|
||||
Create a new `_templates` folder following the [recommended project structure](/docs/guides/functions/development-environment#recommended-project-structure) and add a new `magic-link.tsx` file with the following code:
|
||||
|
||||
@@ -253,7 +253,7 @@ You can find a selection of React Email templates in the [React Email Examples](
|
||||
|
||||
</Admonition>
|
||||
|
||||
### 4. Deploy the Function
|
||||
## 4. Deploy the Function
|
||||
|
||||
Deploy function to Supabase:
|
||||
|
||||
@@ -263,7 +263,7 @@ supabase functions deploy send-email --no-verify-jwt
|
||||
|
||||
Note down the function URL, you will need it in the next step!
|
||||
|
||||
### 5. Configure the Send Email Hook
|
||||
## 5. Configure the Send Email Hook
|
||||
|
||||
- Go to the [Auth Hooks](/dashboard/project/_/auth/hooks) section of the Supabase dashboard and create a new "Send Email hook".
|
||||
- Select HTTPS as the hook type.
|
||||
|
||||
@@ -14,11 +14,11 @@ Edge Functions currently doesn't support image processing libraries such as `Sha
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have the latest version of the [Supabase CLI](/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) installed.
|
||||
|
||||
### Create the Edge Function
|
||||
## Create the Edge Function
|
||||
|
||||
Create a new function locally:
|
||||
|
||||
@@ -27,7 +27,7 @@ supabase functions new image-blur
|
||||
|
||||
```
|
||||
|
||||
### Write the function
|
||||
## Write the function
|
||||
|
||||
In this example, we are implementing a function allowing users to upload an image and get a blurred thumbnail.
|
||||
|
||||
@@ -38,7 +38,7 @@ path="edge-functions/supabase/functions/image-manipulation/index.ts"
|
||||
lines={[[1, -1]]}
|
||||
/>
|
||||
|
||||
### Test it locally
|
||||
## Test it locally
|
||||
|
||||
You can test the function locally by running:
|
||||
|
||||
@@ -59,7 +59,7 @@ curl --location '<http://localhost:54321/functions/v1/image-blur>' \\
|
||||
|
||||
If you open the `output.png` file you will find a transformed version of your original image.
|
||||
|
||||
### Deploy to your hosted project
|
||||
## Deploy to your hosted project
|
||||
|
||||
Deploy the function to your Supabase project.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ In this tutorial you're implementing three parts:
|
||||
|
||||
You can find the complete example code on [GitHub](https://github.com/supabase/supabase/tree/master/examples/ai/edge-functions)
|
||||
|
||||
### Create the database table and webhook
|
||||
## Create the database table and webhook
|
||||
|
||||
Given the [following table definition](https://github.com/supabase/supabase/blob/master/examples/ai/edge-functions/supabase/migrations/20240408072601_embeddings.sql):
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ tocVideo: 'Qf7XvL1fjvo'
|
||||
|
||||
Sending emails from Edge Functions using the [Resend API](https://resend.com/).
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
To get the most out of this guide, you’ll need to:
|
||||
|
||||
@@ -15,7 +15,7 @@ To get the most out of this guide, you’ll need to:
|
||||
|
||||
Make sure you have the latest version of the [Supabase CLI](/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) installed.
|
||||
|
||||
### 1. Create Supabase function
|
||||
## 1. Create Supabase function
|
||||
|
||||
Create a new function locally:
|
||||
|
||||
@@ -25,7 +25,7 @@ supabase functions new resend
|
||||
|
||||
Store the `RESEND_API_KEY` in your `.env` file.
|
||||
|
||||
### 2. Edit the handler function
|
||||
## 2. Edit the handler function
|
||||
|
||||
Paste the following code into the `index.ts` file:
|
||||
|
||||
@@ -57,7 +57,7 @@ const handler = async (_request: Request): Promise<Response> => {
|
||||
export default { fetch: withSupabase({ auth: ['user', 'secret'] }, handler) }
|
||||
```
|
||||
|
||||
### 3. Deploy and send email
|
||||
## 3. Deploy and send email
|
||||
|
||||
Run function locally:
|
||||
|
||||
@@ -85,6 +85,6 @@ When you deploy to Supabase, make sure that your `RESEND_API_KEY` is set in [Edg
|
||||
|
||||
</Admonition>
|
||||
|
||||
### 4. Try it yourself
|
||||
## 4. Try it yourself
|
||||
|
||||
Find the complete example on [GitHub](https://github.com/resendlabs/resend-supabase-edge-functions-example).
|
||||
@@ -5,12 +5,12 @@ description: 'Monitor Edge Functions with the Sentry Deno SDK.'
|
||||
|
||||
Add the [Sentry Deno SDK](https://docs.sentry.io/platforms/javascript/guides/deno/) to your Supabase Edge Functions to track exceptions and get notified of errors or performance issues.
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
- [Create a Sentry account](https://sentry.io/signup/).
|
||||
- Make sure you have the latest version of the [Supabase CLI](/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) installed.
|
||||
|
||||
### 1. Create Supabase function
|
||||
## 1. Create Supabase function
|
||||
|
||||
Create a new function locally:
|
||||
|
||||
@@ -18,7 +18,7 @@ Create a new function locally:
|
||||
supabase functions new sentryfied
|
||||
```
|
||||
|
||||
### 2. Add the Sentry Deno SDK
|
||||
## 2. Add the Sentry Deno SDK
|
||||
|
||||
Handle exceptions within your function and send them to Sentry.
|
||||
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Deploy and test
|
||||
## 3. Deploy and test
|
||||
|
||||
Run function locally:
|
||||
|
||||
@@ -78,7 +78,7 @@ Deploy function to Supabase:
|
||||
supabase functions deploy sentryfied --no-verify-jwt
|
||||
```
|
||||
|
||||
### 4. Try it yourself
|
||||
## 4. Try it yourself
|
||||
|
||||
Find the complete example on [GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/sentryfied/index.ts).
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ For example, libraries like [magick-wasm](/docs/guides/functions/examples/image-
|
||||
|
||||
---
|
||||
|
||||
### Writing a Wasm module
|
||||
## Writing a Wasm module
|
||||
|
||||
You can use different languages and SDKs to write Wasm modules. For this tutorial, we will write a basic Wasm module in Rust that adds two numbers.
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ hideToc: true
|
||||
|
||||
</div>
|
||||
|
||||
### Use cases
|
||||
## Use cases
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/ai#examples" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
@@ -71,7 +71,7 @@ hideToc: true
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
### Framework quickstarts
|
||||
## Framework quickstarts
|
||||
|
||||
<$Show if="docs:framework_quickstarts">
|
||||
|
||||
@@ -224,7 +224,7 @@ hideToc: true
|
||||
|
||||
<$Show if="docs:web_apps">
|
||||
|
||||
### Web app demos
|
||||
## Web app demos
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/getting-started/tutorials/with-nextjs" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
@@ -305,7 +305,7 @@ hideToc: true
|
||||
|
||||
<$Show if="docs:mobile_tutorials">
|
||||
|
||||
### Mobile tutorials
|
||||
## Mobile tutorials
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<$Show if="sdk:dart">
|
||||
|
||||
@@ -7,7 +7,7 @@ You can purchase Supabase through the AWS Marketplace. Buying through AWS Market
|
||||
|
||||
When you make a purchase on AWS Marketplace, AWS will calculate sales taxes, VAT, GST, service tax, etc. (“Indirect Taxes”), if applicable, based on the location of your AWS account. You can find more details in the [AWS tax help guide](https://aws.amazon.com/tax-help/marketplace-buyers/).
|
||||
|
||||
### Plans available through the AWS Marketplace
|
||||
## Plans available through the AWS Marketplace
|
||||
|
||||
- Free Plan: not available
|
||||
- Pro Plan: available, self-serve
|
||||
|
||||
@@ -3,19 +3,19 @@ id: 'aws-marketplace-faq'
|
||||
title: 'AWS Marketplace FAQ'
|
||||
---
|
||||
|
||||
#### The payment for completing the subscription on the AWS Marketplace fails.
|
||||
## The payment for completing the subscription on the AWS Marketplace fails.
|
||||
|
||||
For more information on payment errors, refer to the [AWS documentation](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-paying-for-products.html#payment-methods).
|
||||
|
||||
#### How can the Spend Cap for an organization managed through the AWS Marketplace be enabled?
|
||||
## How can the Spend Cap for an organization managed through the AWS Marketplace be enabled?
|
||||
|
||||
For organizations on the Pro Plan that are managed through the AWS Marketplace, the Spend Cap is not available.
|
||||
In your AWS account, you can set up a budget for marketplace purchases (or for a specific marketplace product) and receive notifications once the budget is exceeded.
|
||||
|
||||
#### How to cancel your AWS Marketplace subscription
|
||||
## How to cancel your AWS Marketplace subscription
|
||||
|
||||
You can cancel your marketplace subscription within 48 hours of purchase. To do so, open a support ticket via the Supabase dashboard. After the 48-hour period, cancellation is no longer possible. If you cancel within the first 48 hours, the upfront charge for the fixed subscription fee will be refunded. Any usage costs incurred up to that point will not be refunded.
|
||||
|
||||
#### Does purchasing Supabase through the AWS Marketplace count toward your AWS spend commitment?
|
||||
## Does purchasing Supabase through the AWS Marketplace count toward your AWS spend commitment?
|
||||
|
||||
Yes, marketplace purchases do count toward the spend commitment.
|
||||
@@ -9,26 +9,26 @@ subtitle: 'This documentation covers frequently asked questions around subscript
|
||||
|
||||
## Organizations and projects
|
||||
|
||||
#### What are organizations and projects?
|
||||
### What are organizations and projects?
|
||||
|
||||
The Supabase Platform has "organizations" and "projects". An organization may contain multiple projects. Each project is a dedicated Supabase instance with all of its sub-services including Storage, Auth, Functions and Realtime.
|
||||
Each organization only has a single subscription with a single plan (Free, Pro, Team or Enterprise). Project add-ons such as [Compute](/docs/guides/platform/compute-and-disk), [IPv4](/docs/guides/platform/ipv4-address), [Log Drains](/docs/guides/telemetry/log-drains), [Advanced MFA](/docs/guides/auth/auth-mfa/phone), [Custom Domains](/docs/guides/platform/custom-domains) and [PITR](/docs/guides/platform/backups#point-in-time-recovery) are configured per project and are added to your organization subscription.
|
||||
|
||||
Read more on [About billing on Supabase](/docs/guides/platform/billing-on-supabase#organization-based-billing).
|
||||
|
||||
#### How many free projects can I have?
|
||||
### How many free projects can I have?
|
||||
|
||||
You are entitled to two active free projects. Paused projects do not count towards your quota. Note that within an organization, we count the free project limits from all members that are either Owner or Admin. If you’ve got another organization member with the Admin or Owner role that has already exhausted their free project quota, you won’t be able to launch another free project in that organization. You can create another Free Plan organization or change the role of the affected member in your [organization’s team settings](/dashboard/org/_/team).
|
||||
|
||||
#### Can I mix free and paid projects in a single organization?
|
||||
### Can I mix free and paid projects in a single organization?
|
||||
|
||||
The subscription plan is set on the organization level and it is not possible to mix paid and non-paid projects inside a single organization. However, you can have a paid and a free organization and make use of the [self-serve project transfers](/docs/guides/platform/project-transfer) to organize your projects. All projects in an organization benefit from the subscription plan. If your organization is on the Pro Plan, all projects within the organization benefit from no project pausing, automated backups and so on.
|
||||
|
||||
#### Can I transfer my projects to another organization?
|
||||
### Can I transfer my projects to another organization?
|
||||
|
||||
Yes, you can transfer your projects to another organization. You can find instructions on how to transfer your projects [here](/docs/guides/platform/project-transfer).
|
||||
|
||||
#### Can I transfer my credits to another organization?
|
||||
### Can I transfer my credits to another organization?
|
||||
|
||||
Yes, you can transfer the credits to another organization. Submit a [support ticket](https://supabase.help).
|
||||
|
||||
@@ -36,11 +36,11 @@ Yes, you can transfer the credits to another organization. Submit a [support tic
|
||||
|
||||
See the [Pricing page](/pricing) for details.
|
||||
|
||||
#### Are there any charges for paused projects?
|
||||
### Are there any charges for paused projects?
|
||||
|
||||
No, we do not charge for paused projects. Compute hours are only counted for active instances. Paused projects do not incur any compute usage charges.
|
||||
|
||||
#### How are multiple projects billed under a paid organization?
|
||||
### How are multiple projects billed under a paid organization?
|
||||
|
||||
We provide a dedicated server for every Supabase project. Each paid organization comes with <Price price="10" /> in Compute Credits to cover one project on the default compute size. Additional projects start at ~<Price price="10" /> a month (billed hourly).
|
||||
|
||||
@@ -52,7 +52,7 @@ Running 3 projects in a Pro Plan organization on the default Micro instance:
|
||||
|
||||
Refer to our [Compute](/docs/guides/platform/manage-your-usage/compute#billing-examples) docs for more examples and insights.
|
||||
|
||||
#### How does compute billing work?
|
||||
### How does compute billing work?
|
||||
|
||||
Each Supabase project is a dedicated VM and Postgres database. By default, your instance runs on the Micro compute instance. You have the option to upgrade your compute size in your [Project settings](/dashboard/project/_/settings/addons). See [Compute Add-ons](/docs/guides/platform/compute-and-disk) for available options.
|
||||
|
||||
@@ -64,7 +64,7 @@ If you upgrade your project to a larger instance for 10 hours and then downgrade
|
||||
|
||||
Read more about [Compute usage](/docs/guides/platform/manage-your-usage/compute).
|
||||
|
||||
#### What is egress and how is it billed?
|
||||
### What is egress and how is it billed?
|
||||
|
||||
Egress refers to the total bandwidth (network traffic) quota available to each organization. This quota can be used for various purposes such as Storage, Realtime, Auth, Functions, Supavisor, Log Drains and Database. Each plan includes a specific egress quota, and any additional usage beyond that quota is billed accordingly.
|
||||
|
||||
@@ -74,41 +74,41 @@ Read more about [Egress usage](/docs/guides/platform/manage-your-usage/egress).
|
||||
|
||||
## Plans and subscriptions
|
||||
|
||||
#### How do I change my subscription plan?
|
||||
### How do I change my subscription plan?
|
||||
|
||||
Change your subscription plan in your [organization's billing settings](/dashboard/org/_/billing). To upgrade to an Enterprise Plan, complete the [Enterprise request form](https://forms.supabase.com/enterprise).
|
||||
|
||||
#### What happens if I cancel my subscription?
|
||||
### What happens if I cancel my subscription?
|
||||
|
||||
The organization is given [credits](/docs/guides/platform/credits) for unused time on the subscription plan. The credits will not expire and can be used again in the future. You may see an additional charge for unbilled excessive usage charges from your previous billing cycle.
|
||||
|
||||
Read more about [downgrades](/docs/guides/platform/manage-your-subscription#downgrade).
|
||||
|
||||
#### I mistakenly upgraded the wrong organization and then downgraded it. Could you issue a refund?
|
||||
### I mistakenly upgraded the wrong organization and then downgraded it. Could you issue a refund?
|
||||
|
||||
We can transfer the amount as [credits](/docs/guides/platform/credits) to another organization of your choice. You can use these credits to upgrade the organization, or if you have already upgraded, the credits will be used to pay the next month's invoice. Please create a [support ticket](https://supabase.help) for this case.
|
||||
|
||||
#### How do I get an annual subscription?
|
||||
### How do I get an annual subscription?
|
||||
|
||||
We currently do not support annual plans officially. However, you can do a [credit top-up](/docs/guides/platform/credits#credit-top-ups) to avoid monthly payments.
|
||||
|
||||
## Quotas and spend caps
|
||||
|
||||
#### What will happen when I exceed the Free Plan quota?
|
||||
### What will happen when I exceed the Free Plan quota?
|
||||
|
||||
You will be notified when you exceed the Free Plan quota. It is important to take action at this point. If you continue to exceed the limits, service restrictions will apply. To avoid service restrictions, you can [manage your usage](/docs/guides/platform/manage-your-usage) or upgrade to a paid plan. Learn more about restrictions in the [Fair Use Policy](#fair-use-policy) section.
|
||||
|
||||
#### What will happen when I exceed the Pro Plan quota and have the spend cap on?
|
||||
### What will happen when I exceed the Pro Plan quota and have the spend cap on?
|
||||
|
||||
You will be notified when you exceed your Pro Plan quota. To unblock yourself, you can toggle off your spend cap in your [organization's billing settings](/dashboard/org/_/billing) to pay for over-usage beyond the Pro plans limits. If you continue to exceed the limits without managing your usage or turning off the spend cap, restrictions will apply. Learn more about restrictions in the [Fair Use Policy](#fair-use-policy) section.
|
||||
|
||||
#### How do I scale beyond the limits of my Pro Plan?
|
||||
### How do I scale beyond the limits of my Pro Plan?
|
||||
|
||||
The Pro Plan has a Spend Cap enabled by default to keep costs under control. If you want to scale beyond the plan's included quota, switch off the Spend Cap to pay for additional usage beyond the plans included limits. You can toggle the Spend Cap in the [organization's billing settings](/dashboard/org/_/billing). Read more about the [Spend Cap](/docs/guides/platform/cost-control#spend-cap).
|
||||
|
||||
## Fair Use Policy
|
||||
|
||||
#### What is the Fair Use Policy?
|
||||
### What is the Fair Use Policy?
|
||||
|
||||
Our Fair Use Policy gives developers the freedom to build and experiment with Supabase, while protecting our infrastructure. Under the Fair Use policy, service restrictions may apply to your organization if:
|
||||
|
||||
@@ -119,13 +119,13 @@ Our Fair Use Policy gives developers the freedom to build and experiment with Su
|
||||
|
||||
You will receive a notification before Fair Use Policy restrictions are applied. However, in some cases, like suspected abuse of our services, restrictions may be applied without prior notice.
|
||||
|
||||
#### What is a grace period and does it reset after usage drops?
|
||||
### What is a grace period and does it reset after usage drops?
|
||||
|
||||
When your organization exceeds plan limits, you receive a grace period before fair use policy applies. After this grace period ends, the dashboard will continue to show a notice indicating that your grace period is over, even if you have dropped back under plan limits. This is a warning that serves as an indicator that your organization previously exceeded usage limits.
|
||||
|
||||
This persistent warning means that if you exceed your plan limits again, you will not receive another grace period and your project will be restricted. The notice and indicator will automatically clear if you continue to stay under plan limits for multiple billing cycles.
|
||||
|
||||
#### How is the Fair Use Policy applied?
|
||||
### How is the Fair Use Policy applied?
|
||||
|
||||
The Fair Use Policy is applied through service restrictions. This could mean:
|
||||
|
||||
@@ -136,7 +136,7 @@ The Fair Use Policy is applied through service restrictions. This could mean:
|
||||
|
||||
The Fair Use Policy is generally applied to all projects of the restricted organization.
|
||||
|
||||
#### How can I remove restrictions applied from the Fair Use Policy?
|
||||
### How can I remove restrictions applied from the Fair Use Policy?
|
||||
|
||||
To remove restrictions, you will need to address the issue that caused the restriction. This could be reducing your usage, paying overdue invoices, updating your payment method, or any other issue that caused the restriction. Once the issue is resolved, the restriction will be lifted.
|
||||
|
||||
@@ -150,69 +150,69 @@ Pausing or deleting a project stops new usage from accumulating, but does not re
|
||||
|
||||
## Reports and invoices
|
||||
|
||||
#### Where do I find my invoices?
|
||||
### Where do I find my invoices?
|
||||
|
||||
You can find all invoices from your organization on your [organization’s invoices page](/dashboard/org/_/billing#invoices).
|
||||
|
||||
#### Where can I see a breakdown of usage?
|
||||
### Where can I see a breakdown of usage?
|
||||
|
||||
You can find the breakdown of your usage on your [organization’s usage page](/dashboard/org/_/usage).
|
||||
|
||||
#### Where can I check my credit balance?
|
||||
### Where can I check my credit balance?
|
||||
|
||||
You can check your Credit balance on the [organization’s billing page](/dashboard/org/_/billing). Credits will be used on future invoices before charging your payment method. If you have enough credits to cover an invoice, there is no charge at all.
|
||||
|
||||
#### Can I change the details of an existing invoice?
|
||||
### Can I change the details of an existing invoice?
|
||||
|
||||
Any changes made to your billing details will only be reflected in your upcoming invoices. Our payment provider cannot regenerate previous invoices. Therefore, make sure to update the billing details before the upcoming invoices are finalized.
|
||||
|
||||
## Payments and billing cycle
|
||||
|
||||
#### What payment methods are available?
|
||||
### What payment methods are available?
|
||||
|
||||
We accept credit card payments only. If you cannot pay via credit card, we do offer alternatives for larger upfront payments. Create a [support ticket](https://supabase.help) in case you’re interested.
|
||||
|
||||
#### What credit card brands are supported?
|
||||
### What credit card brands are supported?
|
||||
|
||||
Visa, Mastercard, American Express, Japan Credit Bureau (JCB), China UnionPay (CUP), Cartes Bancaires
|
||||
|
||||
#### What currency can I pay in?
|
||||
### What currency can I pay in?
|
||||
|
||||
All our invoices are issued in USD, but you can pay in any currency so long as the credit card provider allows charging in USD after conversion.
|
||||
|
||||
#### Can I change the payment method?
|
||||
### Can I change the payment method?
|
||||
|
||||
Yes, you will have to add the new payment method before being allowed to remove the old one.
|
||||
This can be done from your dashboard on the [organization’s billing page](/dashboard/org/_/billing).
|
||||
|
||||
Read more on [Manage your payment methods](/docs/guides/platform/manage-your-subscription#manage-your-payment-methods).
|
||||
|
||||
#### Can I pay upfront for multiple months?
|
||||
### Can I pay upfront for multiple months?
|
||||
|
||||
You can top up your credit balance to cover multiple months through your [organization’s billing page](/dashboard/org/_/billing).
|
||||
|
||||
Read more on [Credit top-ups](/docs/guides/platform/credits#credit-top-ups).
|
||||
|
||||
#### When are payments taken?
|
||||
### When are payments taken?
|
||||
|
||||
Payments are taken at the beginning of each billing cycle. You will be charged once a month. You can see the current billing cycle and upcoming invoice in your [organization's billing settings](/dashboard/org/_/billing). The subscription plan fee is charged upfront, whereas usage-charges, including compute, are charged in arrears based on your usage.
|
||||
|
||||
Read more on [Your monthly invoice](/docs/guides/platform/your-monthly-invoice).
|
||||
|
||||
#### Where can I change my billing details?
|
||||
### Where can I change my billing details?
|
||||
|
||||
You can update your billing details on the [organization’s billing page](/dashboard/org/_/billing).
|
||||
Note that any changes made to your billing details will only be reflected in your upcoming invoices. Our payment provider cannot regenerate previous invoices.
|
||||
|
||||
#### What happens if I am unable to make the payment?
|
||||
### What happens if I am unable to make the payment?
|
||||
|
||||
When an invoice becomes overdue, we will pause your projects and downgrade your organization to the Free Plan. You will be able to restore your projects once you have paid all outstanding invoices.
|
||||
|
||||
#### Can I use a credit top-up to pay an outstanding invoice?
|
||||
### Can I use a credit top-up to pay an outstanding invoice?
|
||||
|
||||
Credit top-ups apply only to future invoices. They cannot be used to pay or adjust outstanding invoices.
|
||||
|
||||
#### Why am I overdue?
|
||||
### Why am I overdue?
|
||||
|
||||
We were unable to charge your payment method. This likely means that the payment was not successfully processed with the credit card on your account profile.
|
||||
You can be overdue when
|
||||
@@ -227,39 +227,39 @@ If you are still facing issues, raise a [support ticket](https://supabase.help).
|
||||
|
||||
Payments are always in USD and may show up as coming from Singapore, given our payment entity is in Singapore. Make sure you allow payments from Singapore and in USD
|
||||
|
||||
#### Can I delay my payment?
|
||||
### Can I delay my payment?
|
||||
|
||||
No, you cannot delay your payment.
|
||||
|
||||
#### Can I get a refund of my unused credits?
|
||||
### Can I get a refund of my unused credits?
|
||||
|
||||
No, we do not provide refunds. Please refer to our [Terms of Service](/terms#1-fees).
|
||||
|
||||
#### What do I do if my bill looks wrong?
|
||||
### What do I do if my bill looks wrong?
|
||||
|
||||
Take a moment to review our [Your monthly invoice](/docs/guides/platform/your-monthly-invoice) page, which may help clarify any questions about your invoice. If it still looks wrong, submit a [support ticket](https://supabase.help) through the dashboard. Select the affected organization and provide the invoice number for us to look at your case.
|
||||
|
||||
## Taxes
|
||||
|
||||
#### Does Supabase charge sales tax, VAT or GST?
|
||||
### Does Supabase charge sales tax, VAT or GST?
|
||||
|
||||
Supabase is rolling out sales tax in applicable US states, and VAT, GST, and other indirect taxes for customers where required by law. The tax amount applied to your invoice depends on your billing address and the tax regulations in your jurisdiction.
|
||||
|
||||
#### Why is Supabase collecting tax now?
|
||||
### Why is Supabase collecting tax now?
|
||||
|
||||
As a cloud services provider operating globally, Supabase is required to collect and remit indirect taxes in an increasing number of jurisdictions. We’re updating our billing practices to meet these obligations and ensure compliance with local tax regulations.
|
||||
|
||||
#### Will every customer be charged tax?
|
||||
### Will every customer be charged tax?
|
||||
|
||||
No. Tax is only applied in jurisdictions where Supabase is registered to collect it. If your billing address is in one of those jurisdictions, you’ll see tax applied on your invoice. If it is not, your invoices will not include tax.
|
||||
|
||||
#### When will customers start seeing tax on their invoices?
|
||||
### When will customers start seeing tax on their invoices?
|
||||
|
||||
We are progressively rolling out tax collection across international jurisdictions. The roll out begins on May 1, 2026 and completes by June 30, 2026.
|
||||
|
||||
You will receive an email notification in advance of any changes to your invoicing.
|
||||
|
||||
#### Do I need to do anything?
|
||||
### Do I need to do anything?
|
||||
|
||||
For most customers, nothing changes on your end. Supabase automatically calculates the applicable tax based on the billing address associated with your organization.
|
||||
|
||||
@@ -268,11 +268,11 @@ There are two cases where action may be needed:
|
||||
- If your organization is VAT- or GST-registered, make sure you have entered a valid Tax ID in your [organization’s billing page](/dashboard/org/_/billing#address). This allows us to apply the correct tax treatment, such as reverse charge for eligible B2B transactions.
|
||||
- If your organization is tax-exempt, submit your exemption certificate to [tax-documents@supabase.io](mailto:tax-documents@supabase.io) so we can verify and apply the exemption to your organization.
|
||||
|
||||
#### What if my billing address is missing or incorrect?
|
||||
### What if my billing address is missing or incorrect?
|
||||
|
||||
A valid billing address is required for us to calculate the correct tax and comply with tax regulations. Make sure your billing address is up to date in your [organization’s billing page](/dashboard/org/_/billing#address) to avoid any disruption.
|
||||
|
||||
#### Where do I add my tax ID?
|
||||
### Where do I add my tax ID?
|
||||
|
||||
You can add or update your Tax ID directly in the Supabase Dashboard under your [organization’s billing page](/dashboard/org/_/billing#address).
|
||||
|
||||
@@ -280,24 +280,24 @@ Providing a valid Tax ID ensures we apply the correct tax treatment for your reg
|
||||
|
||||
If you do not see an option for your country’s Tax ID format, please open a [support ticket](https://supabase.help) and we’ll make sure it is recorded on your account.
|
||||
|
||||
#### What if my organization is tax-exempt?
|
||||
### What if my organization is tax-exempt?
|
||||
|
||||
If your organization qualifies for a tax exemption, email your exemption certificate to [tax-documents@supabase.io](mailto:tax-documents@supabase.io).
|
||||
|
||||
Our team will verify the certificate and update your account accordingly. Once approved, tax will no longer be applied to your invoices.
|
||||
|
||||
#### How does tax appear on my invoices?
|
||||
### How does tax appear on my invoices?
|
||||
|
||||
Tax is shown separately at the bottom of your invoice, clearly broken out from the cost of the products and services you’re subscribed to. This makes it easy to distinguish between your subscription costs and any applicable tax.
|
||||
|
||||
#### How is tax handled on prepaid credit top ups or packages?
|
||||
### How is tax handled on prepaid credit top ups or packages?
|
||||
|
||||
If you purchase a prepaid top up or credit package, tax is assessed at the time of purchase, not when the credits are later consumed against usage or subscription invoices. This ensures the correct tax rate is applied based on your billing address at the time of purchase.
|
||||
|
||||
#### Are marketplace purchases affected?
|
||||
### Are marketplace purchases affected?
|
||||
|
||||
If you use Supabase through a cloud marketplace such as AWS Marketplace or Vercel Marketplace, the marketplace provider handles tax collection and remittance. In those cases, Supabase does not separately charge tax on marketplace-billed invoices.
|
||||
|
||||
#### Who should I contact with questions about tax?
|
||||
### Who should I contact with questions about tax?
|
||||
|
||||
For questions about tax collection, exemptions, or your Tax ID, please open a [support ticket](https://supabase.help).
|
||||
@@ -100,7 +100,7 @@ nslookup db.<PROJECT_REF>.supabase.co
|
||||
|
||||
The pooler and direct connection strings can be found in the [project connect page](/dashboard/project/_?showConnect=true):
|
||||
|
||||
#### Direct connection
|
||||
### Direct connection
|
||||
|
||||
IPv6 unless IPv4 Add-On is enabled
|
||||
|
||||
@@ -109,7 +109,7 @@ IPv6 unless IPv4 Add-On is enabled
|
||||
postgresql://postgres:[YOUR-PASSWORD]@db.ajrbwkcuthywfihaarmflo.supabase.co:5432/postgres
|
||||
```
|
||||
|
||||
#### Supavisor in transaction mode (port 6543)
|
||||
### Supavisor in transaction mode (port 6543)
|
||||
|
||||
Always uses an IPv4 address
|
||||
|
||||
@@ -118,7 +118,7 @@ Always uses an IPv4 address
|
||||
postgresql://postgres.ajrbwkcuthywddfihrmflo:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
|
||||
```
|
||||
|
||||
#### Supavisor in session mode (port 5432)
|
||||
### Supavisor in session mode (port 5432)
|
||||
|
||||
Always uses an IPv4 address
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ These steps cover a manual logical restore (`pg_dump` / `psql`) into a project y
|
||||
|
||||
### Special considerations
|
||||
|
||||
##### Preserving migration history
|
||||
#### Preserving migration history
|
||||
|
||||
If you were using Supabase CLI for managing migrations on your old database and would like to preserve the migration history in your newly restored project, you need to insert the migration records separately using the following commands.
|
||||
|
||||
@@ -228,7 +228,7 @@ psql \
|
||||
--dbname "$NEW_DB_URL"
|
||||
```
|
||||
|
||||
##### Schema changes to `auth` and `storage`
|
||||
#### Schema changes to `auth` and `storage`
|
||||
|
||||
If you have modified the `auth` and `storage` schemas in your old project, such as adding triggers or Row Level Security(RLS) policies, you have to restore them separately. The Supabase CLI can help you diff the changes to these schemas using the following commands.
|
||||
|
||||
@@ -239,11 +239,11 @@ supabase db diff --linked --schema auth,storage > changes.sql
|
||||
|
||||
### Troubleshooting notes
|
||||
|
||||
##### Disabling triggers during restore:
|
||||
#### Disabling triggers during restore:
|
||||
|
||||
Setting `session_replication_role` to `replica` disables triggers during the migration, preventing columns from being double encrypted.
|
||||
|
||||
##### Custom roles require passwords
|
||||
#### Custom roles require passwords
|
||||
|
||||
If you created any [custom roles](/dashboard/project/_/database/roles) with the `LOGIN` attribute, you must manually set their passwords in the new project. This can be done with the SQL command:
|
||||
|
||||
@@ -251,7 +251,7 @@ If you created any [custom roles](/dashboard/project/_/database/roles) with the
|
||||
alter user "YOUR_USER" with password 'SOME_NEW_PASSWORD';
|
||||
```
|
||||
|
||||
##### `supabase_admin` permission errors
|
||||
#### `supabase_admin` permission errors
|
||||
|
||||
If you encounter permission errors related to `supabase_admin` during restore:
|
||||
|
||||
@@ -262,7 +262,7 @@ If you encounter permission errors related to `supabase_admin` during restore:
|
||||
ALTER ... OWNER TO "supabase_admin"
|
||||
```
|
||||
|
||||
##### `cli_login_postgres` role grant error
|
||||
#### `cli_login_postgres` role grant error
|
||||
|
||||
If you encounter the error:
|
||||
|
||||
@@ -278,7 +278,7 @@ DETAIL: Only roles with the ADMIN option on role "postgres" may grant this role
|
||||
GRANT "postgres" TO "cli_login_postgres" WITH INHERIT FALSE GRANTED BY "supabase_admin";
|
||||
```
|
||||
|
||||
##### `cli_login_postgres` role issues after cloning
|
||||
#### `cli_login_postgres` role issues after cloning
|
||||
|
||||
The `cli_login_role` must be created by the `supabase_admin` role. If the migration process cloned over the role before the CLI could generate its own version, it may encounter the error:
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ To use PrivateLink with your Supabase project:
|
||||
|
||||
## Getting started
|
||||
|
||||
#### Step 1: Add AWS account
|
||||
### Step 1: Add AWS account
|
||||
|
||||
Navigate to your project's Integrations section to set up PrivateLink:
|
||||
|
||||
@@ -52,7 +52,7 @@ Navigate to your project's Integrations section to set up PrivateLink:
|
||||
|
||||
After submission, Supabase creates a VPC Lattice Resource Configuration for your project and sends an AWS Resource Share to the specified AWS Account ID. This process may take a few moments. Once complete, the account will show a "Ready" status, indicating that the resource share has been sent to your AWS account and is ready to be accepted.
|
||||
|
||||
#### Step 2: Accept resource share
|
||||
### Step 2: Accept resource share
|
||||
|
||||
Supabase will send you an AWS Resource Share containing the VPC Lattice Resource Configurations for your projects. To accept this share:
|
||||
|
||||
@@ -69,7 +69,7 @@ Supabase will send you an AWS Resource Share containing the VPC Lattice Resource
|
||||
{/* 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
|
||||
### Step 3: Configure security groups
|
||||
|
||||
Ensure your security groups allow traffic on the appropriate ports:
|
||||
|
||||
@@ -81,11 +81,11 @@ Ensure your security groups allow traffic on the appropriate ports:
|
||||
- Destination that is appropriate for your network. i.e. the subnet of your VPC or security group of your application instances
|
||||
5. Finish creating the security group by clicking **Create security group**
|
||||
|
||||
#### Step 4: Create connection
|
||||
### Step 4: Create connection
|
||||
|
||||
In your AWS account, you have two options to establish connectivity:
|
||||
|
||||
##### Option A: Create a PrivateLink endpoint
|
||||
#### Option A: Create a PrivateLink endpoint
|
||||
|
||||
1. Navigate to the VPC console in your AWS account
|
||||
2. Go to [Endpoints](https://console.aws.amazon.com/vpcconsole/home#Endpoints:) in the left sidebar
|
||||
@@ -106,7 +106,7 @@ In your AWS account, you have two options to establish connectivity:
|
||||
- The IP addresses of the endpoint will be listed in the **Subnets** section of the endpoint details
|
||||
- The DNS record will be in the **Associations** section of the endpoint details in the **DNS Name** field if you enabled it in step 8
|
||||
|
||||
##### Option B: Attach resource configuration to an existing VPC lattice service network
|
||||
#### Option B: Attach resource configuration to an existing VPC lattice service network
|
||||
|
||||
1. **This method is only recommended if you have an existing VPC Lattice Service Network**
|
||||
2. Navigate to the VPC Lattice console in your AWS account
|
||||
@@ -118,7 +118,7 @@ In your AWS account, you have two options to establish connectivity:
|
||||
8. After creation, you will see the resource configuration in the Resource configurations section of your service network with the status "Active"
|
||||
9. For connectivity, click on the association details and the domain name will be listed in the **DNS entries** section
|
||||
|
||||
#### Step 5: Test connectivity
|
||||
### Step 5: Test connectivity
|
||||
|
||||
Verify the private connection is working correctly from your VPC:
|
||||
|
||||
@@ -132,7 +132,7 @@ psql "postgresql://[username]:[password]@[private-endpoint]:5432/postgres"
|
||||
|
||||
You should see a successful connection without any public internet traffic.
|
||||
|
||||
#### Step 6: Update applications
|
||||
### Step 6: Update applications
|
||||
|
||||
Configure your applications to use the private connection details:
|
||||
|
||||
@@ -151,7 +151,7 @@ postgresql://user:pass@db.[project-ref].supabase.co:5432/postgres
|
||||
postgresql://user:pass@your-private-endpoint.vpce.amazonaws.com:5432/postgres
|
||||
```
|
||||
|
||||
#### Step 7: Disable public connectivity (optional)
|
||||
### Step 7: Disable public connectivity (optional)
|
||||
|
||||
For maximum security, you can disable public internet access for your database:
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ When you create a Queue in Supabase, you can choose to create helper database fu
|
||||
|
||||
Database functions in `pgmq_public` can be exposed via Supabase Data API so consumers client-side can call them. Visit the [Quickstart](/docs/guides/queues/quickstart) for an example.
|
||||
|
||||
### `pgmq_public.pop(queue_name)`
|
||||
## `pgmq_public.pop(queue_name)`
|
||||
|
||||
Retrieves the next available message and deletes it from the specified Queue.
|
||||
|
||||
@@ -15,7 +15,7 @@ Retrieves the next available message and deletes it from the specified Queue.
|
||||
|
||||
---
|
||||
|
||||
### `pgmq_public.send(queue_name, message, sleep_seconds)`
|
||||
## `pgmq_public.send(queue_name, message, sleep_seconds)`
|
||||
|
||||
Adds a Message to the specified Queue, optionally delaying its visibility to all consumers by a number of seconds.
|
||||
|
||||
@@ -25,7 +25,7 @@ Adds a Message to the specified Queue, optionally delaying its visibility to all
|
||||
|
||||
---
|
||||
|
||||
### `pgmq_public.send_batch(queue_name, messages, sleep_seconds)`
|
||||
## `pgmq_public.send_batch(queue_name, messages, sleep_seconds)`
|
||||
|
||||
Adds a batch of Messages to the specified Queue, optionally delaying their availability to all consumers by a number of seconds.
|
||||
|
||||
@@ -35,7 +35,7 @@ Adds a batch of Messages to the specified Queue, optionally delaying their avail
|
||||
|
||||
---
|
||||
|
||||
### `pgmq_public.archive(queue_name, message_id)`
|
||||
## `pgmq_public.archive(queue_name, message_id)`
|
||||
|
||||
Archives a Message by moving it from the Queue table to the Queue's archive table.
|
||||
|
||||
@@ -44,7 +44,7 @@ Archives a Message by moving it from the Queue table to the Queue's archive tabl
|
||||
|
||||
---
|
||||
|
||||
### `pgmq_public.delete(queue_name, message_id)`
|
||||
## `pgmq_public.delete(queue_name, message_id)`
|
||||
|
||||
Permanently deletes a Message from the specified Queue.
|
||||
|
||||
@@ -53,7 +53,7 @@ Permanently deletes a Message from the specified Queue.
|
||||
|
||||
---
|
||||
|
||||
### `pgmq_public.read(queue_name, sleep_seconds, n)`
|
||||
## `pgmq_public.read(queue_name, sleep_seconds, n)`
|
||||
|
||||
Reads up to "n" Messages from the specified Queue with an optional "sleep_seconds" (visibility timeout).
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ hideToc: true
|
||||
<div>
|
||||
<div className="max-w-xl mb-6">
|
||||
|
||||
### Migrate to Supabase
|
||||
## Migrate to Supabase
|
||||
|
||||
</div>
|
||||
|
||||
@@ -134,7 +134,7 @@ hideToc: true
|
||||
<div>
|
||||
<div className="max-w-xl mb-6">
|
||||
|
||||
### Postgres resources
|
||||
## Postgres resources
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ The hosted Supabase platform has the necessary controls to meet HIPAA requiremen
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Customer responsibilities
|
||||
## Customer responsibilities
|
||||
|
||||
Covered entities (the customer) are organizations that directly handle PHI, such as health plans, healthcare clearinghouses, and healthcare providers that conduct certain electronic transactions.
|
||||
|
||||
@@ -22,7 +22,7 @@ Covered entities (the customer) are organizations that directly handle PHI, such
|
||||
2. **Business Associate Agreements (BAAs)**: Customers must sign a BAA with Supabase. When the covered entity engages a business associate to help carry out its healthcare activities, it must have a written BAA. This agreement outlines the business associate's responsibilities and requires them to comply with HIPAA Rules.
|
||||
3. **Internal Compliance Programs**: Customers must [configure their HIPAA projects](/docs/guides/platform/hipaa-projects) and follow the guidance given by the security advisor. Covered entities are responsible for implementing internal processes and compliance programs to ensure they meet HIPAA requirements.
|
||||
|
||||
### Supabase responsibilities
|
||||
## Supabase responsibilities
|
||||
|
||||
Supabase as the business associate, and the vendors used by Supabase, are the entities that perform functions or activities on behalf of the customer.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ It is the customer’s responsibility to ensure that testing activities are alig
|
||||
|
||||
Furthermore, Supabase runs a [Vulnerability Disclosure Program](https://hackerone.com/ca63b563-9661-4ac3-8d23-7581582ef451/embedded_submissions/new) (VDP) with HackerOne, and external security researchers may report any bugs found within the scope of the aforementioned program. Customer penetration testing does not form part of this VDP.
|
||||
|
||||
### Permitted services
|
||||
## Permitted services
|
||||
|
||||
- Authentication
|
||||
- Database
|
||||
@@ -22,7 +22,7 @@ Furthermore, Supabase runs a [Vulnerability Disclosure Program](https://hackeron
|
||||
- `https://<customer_project_ref>.supabase.co/*`
|
||||
- `https://db.<customer_project_ref>.supabase.co/*`
|
||||
|
||||
### Prohibited testing and activities
|
||||
## Prohibited testing and activities
|
||||
|
||||
- Any activity contrary to what is listed in the AUP.
|
||||
- Denial of Service (DoS) and Distributed Denial of Service (DDoS) testing.
|
||||
|
||||
@@ -25,14 +25,14 @@ Our [HIPAA documentation](/docs/guides/security/hipaa-compliance) provides more
|
||||
|
||||
SOC 2 compliance is a critical aspect of data security for Supabase and our customers. Being fully SOC 2 compliant is a shared responsibility and here’s a breakdown of the responsibilities for both parties:
|
||||
|
||||
#### Supabase responsibilities
|
||||
### Supabase responsibilities
|
||||
|
||||
1. **Security Measures**: Supabase implements robust security controls to protect customer data. These includes measures to prevent data breaches and ensure the confidentiality and integrity of the information managed and stored by the platform. Supabase is obliged to be vigilant about security risks and must demonstrate that our security measures meet industry standards through regular audits.
|
||||
2. **Compliance Audits**: Supabase undergoes SOC 2 audits yearly to verify that our data management practices comply with the Trust Services Criteria (TSC), which include security, availability, processing integrity, confidentiality, and privacy. These audits are conducted by an independent third party.
|
||||
3. **Incident Response**: Supabase has an incident response plan in place to handle data breaches efficiently. This plan outlines how the organization detects issues, responds to incidents, and manages system vulnerabilities.
|
||||
4. **Reporting**: Upon a successful audit, Supabase receive a SOC 2 report that details our compliance status. This report is available to customers as a SOC 2 Type 2 report, and allows customers and stakeholders to assure that Supabase has implemented adequate and the requisite safeguards to protect sensitive information.
|
||||
|
||||
#### Customer responsibilities
|
||||
### Customer responsibilities
|
||||
|
||||
1. **Compliance Requirements**: Understand your own compliance requirements. While SOC 2 compliance is not a legal requirement, many enterprise customers require their providers to have a SOC 2 report. This is because it provides assurance that the provider has implemented robust controls to protect customer data.
|
||||
2. **Due Diligence**: Customers must perform due diligence when selecting Supabase as a provider. This includes reviewing the SOC 2 Type 2 report to ensure that Supabase meets the expected security standards. Customers should also understand the division of responsibilities between themselves and Supabase to avoid duplication of effort.
|
||||
@@ -40,7 +40,7 @@ SOC 2 compliance is a critical aspect of data security for Supabase and our cust
|
||||
4. **Control Compliance**: If a customer needs to be SOC 2 compliant, they should themselves implement the requisite controls and undergo a SOC 2 audit.
|
||||
5. **Audit logging**: Supabase sets [Postgres connection logging](/docs/guides/platform/postgres-connection-logging) to off by default for new projects. If your SOC 2 program requires connection audit evidence, enable connection logging and define how you retain and review those logs.
|
||||
|
||||
#### Shared responsibilities
|
||||
### Shared responsibilities
|
||||
|
||||
1. **Data Security**: Both customers and Supabase share the responsibility of ensuring data security. While the Supabase, as the provider, implements the security controls, the customer must ensure that their use of the Supabase platform does not compromise these controls.
|
||||
2. **Control Compliance**: Supabase asserts through our SOC 2 that all requisite security controls are met. Customers wishing to also be SOC 2 compliant need to go through their own SOC 2 audit, verifying that security controls are met on the customer's side.
|
||||
|
||||
@@ -7,7 +7,7 @@ hideToc: true
|
||||
|
||||
Self-hosting is a good fit if you need full control over your data, have compliance requirements that prevent you from using managed services, or want to run Supabase in an isolated environment.
|
||||
|
||||
### How self-hosted Supabase differs
|
||||
## How self-hosted Supabase differs
|
||||
|
||||
Self-hosted Supabase is different from:
|
||||
|
||||
@@ -16,7 +16,7 @@ Self-hosted Supabase is different from:
|
||||
|
||||
Self-hosted Supabase mimics a single project. Studio doesn't support multiple organizations or projects. Platform-only [features](/features) such as branching, advanced metrics beyond logs, managed backups and PITR, analytics and vector buckets, ETL, and the platform management API are **unavailable** in self-hosted configuration. Most settings are configured through [environment variables](https://github.com/supabase/supabase/blob/master/docker/.env.example).
|
||||
|
||||
### Your responsibilities when self-hosting
|
||||
## Your responsibilities when self-hosting
|
||||
|
||||
When you self-host, **you are responsible for**:
|
||||
|
||||
@@ -28,7 +28,7 @@ When you self-host, **you are responsible for**:
|
||||
- Backups and disaster recovery
|
||||
- Monitoring and uptime
|
||||
|
||||
### Telemetry
|
||||
## Telemetry
|
||||
|
||||
Self-hosted Supabase (run via Docker Compose) **does not phone home or collect any telemetry**.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ sidebar_label: 'CDN'
|
||||
|
||||
All assets uploaded to Supabase Storage are cached on a Content Delivery Network (CDN) to improve the latency for users all around the world. CDNs are a geographically distributed set of servers or **nodes** which cache content from an **origin server**. For Supabase Storage, the origin is the storage server running in the [same region as your project](/dashboard/project/_/settings/general). Aside from performance, CDNs also help with security and availability by mitigating Distributed Denial of Service (DDoS) and other application attacks.
|
||||
|
||||
### Example
|
||||
## Example
|
||||
|
||||
The following example shows how a CDN helps with performance.
|
||||
|
||||
@@ -27,7 +27,7 @@ Note that CDNs might still evict your object from their cache if it has not been
|
||||
|
||||
The cache status of a particular request is sent in the `cf-cache-status` header. A cache status of `MISS` indicates that the CDN node did not have the object in its cache and had to ping the origin to get it. A cache status of `HIT` indicates that the object was sent directly from the CDN.
|
||||
|
||||
### Public vs private buckets
|
||||
## Public vs private buckets
|
||||
|
||||
Objects in public buckets do not require any authorization to access objects. This leads to a better cache hit rate compared to private buckets.
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ For more details on filtering the log tables, see [Advanced Log Filtering](/docs
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Example Storage queries for the Logs Explorer
|
||||
## Example Storage queries for the Logs Explorer
|
||||
|
||||
#### Filter by status 5XX error
|
||||
### Filter by status 5XX error
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -37,7 +37,7 @@ order by timestamp desc
|
||||
limit 100;
|
||||
```
|
||||
|
||||
#### Filter by status 4XX error
|
||||
### Filter by status 4XX error
|
||||
|
||||
```sql
|
||||
select
|
||||
@@ -57,7 +57,7 @@ order by timestamp desc
|
||||
limit 100;
|
||||
```
|
||||
|
||||
#### Filter by method
|
||||
### Filter by method
|
||||
|
||||
```sql
|
||||
select id, storage_logs.timestamp, event_message, r.method
|
||||
@@ -70,7 +70,7 @@ order by timestamp desc
|
||||
limit 100;
|
||||
```
|
||||
|
||||
#### Filter by IP address
|
||||
### Filter by IP address
|
||||
|
||||
```sql
|
||||
select id, storage_logs.timestamp, event_message, r.remoteAddress
|
||||
|
||||
@@ -12,19 +12,19 @@ Here are some optimizations that you can consider to improve performance and red
|
||||
|
||||
If your project has high egress, these optimizations can help reducing it.
|
||||
|
||||
#### Resize images
|
||||
### Resize images
|
||||
|
||||
Images typically make up most of your egress. By keeping them as small as possible, you can cut down on egress and boost your application's performance. You can take advantage of our [Image Transformation](/docs/guides/storage/serving/image-transformations) service to optimize any image on the fly.
|
||||
|
||||
#### Set a high cache-control value
|
||||
### Set a high cache-control value
|
||||
|
||||
Using the browser cache can effectively lower your egress since the asset remains stored in the user's browser after the initial download. Setting a high `cache-control` value ensures the asset stays in the user's browser for an extended period, decreasing the need to download it from the server repeatedly. Read more [here](/docs/guides/storage/cdn/smart-cdn#cache-duration)
|
||||
|
||||
#### Limit the upload size
|
||||
### Limit the upload size
|
||||
|
||||
You have the option to set a maximum upload size for your bucket. Doing this can prevent users from uploading and then downloading excessively large files. You can control the maximum file size by configuring this option at the [bucket level](/docs/guides/storage/buckets/creating-buckets).
|
||||
|
||||
#### Smart CDN
|
||||
### Smart CDN
|
||||
|
||||
By leveraging our [Smart CDN](/docs/guides/storage/cdn/smart-cdn), you can achieve a higher cache hit rate and therefore lower your egress cached, as we charge less for cached egress (see [egress pricing](/docs/guides/platform/manage-your-usage/egress#pricing)).
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ sidebar_label: 'Schema'
|
||||
|
||||
Supabase Storage provides SQL helper functions which you can use to write RLS policies.
|
||||
|
||||
### `storage.filename()`
|
||||
## `storage.filename()`
|
||||
|
||||
Returns the name of a file. For example, if your file is stored in `public/subfolder/avatar.png` it would return: `'avatar.png'`
|
||||
|
||||
@@ -26,7 +26,7 @@ using (
|
||||
);
|
||||
```
|
||||
|
||||
### `storage.foldername()`
|
||||
## `storage.foldername()`
|
||||
|
||||
Returns an array path, with all of the subfolders that a file belongs to. For example, if your file is stored in `public/subfolder/avatar.png` it would return: `[ 'public', 'subfolder' ]`
|
||||
|
||||
@@ -44,7 +44,7 @@ with check (
|
||||
);
|
||||
```
|
||||
|
||||
### `storage.extension()`
|
||||
## `storage.extension()`
|
||||
|
||||
Returns the extension of a file. For example, if your file is stored in `public/subfolder/avatar.png` it would return: `'png'`
|
||||
|
||||
@@ -62,7 +62,7 @@ with check (
|
||||
);
|
||||
```
|
||||
|
||||
### `storage.allow_only_operation()`
|
||||
## `storage.allow_only_operation()`
|
||||
|
||||
Returns `true` when the current Storage API operation exactly matches the provided operation name.
|
||||
|
||||
@@ -92,7 +92,7 @@ using (
|
||||
);
|
||||
```
|
||||
|
||||
### `storage.allow_any_operation()`
|
||||
## `storage.allow_any_operation()`
|
||||
|
||||
Returns `true` when the current Storage API operation exactly matches any operation in the provided array.
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ Our client libraries methods like `getPublicUrl` and `createSignedUrl` support t
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -131,6 +132,7 @@ To share a transformed image in a private bucket for a fixed amount of time, pro
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -206,6 +208,7 @@ To download a transformed image, pass the `transform` option to the `download` f
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -314,6 +317,7 @@ In case you'd like to return the original format of the image and **opt-out** fr
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -459,6 +463,7 @@ Example:
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -567,6 +572,7 @@ Example:
|
||||
|
||||
```ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient('your_project_url', 'your_supabase_api_key')
|
||||
|
||||
// ---cut---
|
||||
@@ -691,7 +697,7 @@ If you run the official self-hosted stack from the [`supabase/supabase`](https:/
|
||||
|
||||
</Admonition>
|
||||
|
||||
#### imgproxy configuration:
|
||||
### imgproxy configuration:
|
||||
|
||||
Deploy an imgproxy container with the following configuration:
|
||||
|
||||
@@ -705,7 +711,7 @@ imgproxy:
|
||||
|
||||
Note: make sure that this service can only be reachable within an internal network and not exposed to the public internet
|
||||
|
||||
#### Storage API configuration:
|
||||
### Storage API configuration:
|
||||
|
||||
Once [imgproxy](https://imgproxy.net/) is deployed we need to configure a couple of environment variables in your self-hosted [`storage-api`](https://github.com/supabase/storage-api) service as follows:
|
||||
|
||||
|
||||
@@ -283,13 +283,13 @@ Instead of `https://project-id.supabase.co` use `https://project-id.storage.supa
|
||||
</$Show>
|
||||
</Tabs>
|
||||
|
||||
### Upload URL
|
||||
## Upload URL
|
||||
|
||||
When uploading using the resumable upload endpoint, the storage server creates a unique URL for each upload, even for multiple uploads to the same path. All chunks will be uploaded to this URL using the `PATCH` method.
|
||||
|
||||
This unique upload URL will be valid for **up to 24 hours**. If the upload is not completed within 24 hours, the URL will expire and you'll need to start the upload again. TUS client libraries typically create a new URL if the previous one expires.
|
||||
|
||||
### Concurrency
|
||||
## Concurrency
|
||||
|
||||
When two or more clients upload to the same upload URL only one of them will succeed. The other clients will receive a `409 Conflict` error. Only 1 client can upload to the same upload URL at a time which prevents data corruption.
|
||||
|
||||
@@ -297,7 +297,7 @@ When two or more clients upload a file to the same path using different upload U
|
||||
|
||||
If you provide the `x-upsert` header the last client to complete the upload will succeed instead.
|
||||
|
||||
### Uppy example
|
||||
## Uppy example
|
||||
|
||||
You can check a [full example using Uppy](https://github.com/supabase/supabase/tree/master/examples/storage/resumable-upload-uppy).
|
||||
|
||||
@@ -308,7 +308,7 @@ Uppy has integrations with different frameworks:
|
||||
- [Vue](https://uppy.io/docs/vue/)
|
||||
- [Angular](https://uppy.io/docs/angular/)
|
||||
|
||||
### Presigned uploads
|
||||
## Presigned uploads
|
||||
|
||||
Resumable uploads also supports using signed upload tokens to created time-limited URLs that you can share to your users by invoking the `createSignedUploadUrl` method on the SDK and including the returned token in the `x-signature` header of the resumable upload.
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ We're currently investigating an issue where the tables responsible for keeping
|
||||
|
||||
We've documented some of the migrations that run into this issue and their corresponding fix here:
|
||||
|
||||
### Auth: `operator does not exist: uuid = text`
|
||||
## Auth: `operator does not exist: uuid = text`
|
||||
|
||||
Temporary fix: Run `insert into auth.schema_migrations values ('20221208132122');` via the [SQL editor](/dashboard/project/_/sql/new) to fix the issue.
|
||||
|
||||
|
||||
+3
-3
@@ -6,16 +6,16 @@ topics = [ "self-hosting" ]
|
||||
database_id = "03854567-8838-4f12-8a6c-095fc1671d9f"
|
||||
---
|
||||
|
||||
### Overview
|
||||
## Overview
|
||||
|
||||
The self-hosted version is pretty similar to the hosted one. It might not always have the latest features right away, but it includes everything you need to get your application up and running.
|
||||
|
||||
### Feature availability
|
||||
## Feature availability
|
||||
|
||||
To know what features are available in the self-hosted version, refer to the comprehensive list here:
|
||||
[Supabase Features](/features)
|
||||
|
||||
### Self-hosting documentation
|
||||
## Self-hosting documentation
|
||||
|
||||
For detailed steps and guidance on how to set up and manage your self-hosted Supabase instance, follow the documentation provided:
|
||||
[Self-Hosting Guide](/docs/guides/self-hosting)
|
||||
+2
-2
@@ -17,7 +17,7 @@ Certain queries, like indexing a table or changing a column's data type, are inh
|
||||
|
||||
To execute long-running queries, follow the below steps.
|
||||
|
||||
### Install an external SQL client
|
||||
## Install an external SQL client
|
||||
|
||||
The guide focuses on [psql](/docs/guides/database/psql) but you can use any Postgres client.
|
||||
|
||||
@@ -41,7 +41,7 @@ If you are working in an [IPv6 environment](https://github.com/orgs/supabase/dis
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Increase the query timeout
|
||||
## Increase the query timeout
|
||||
|
||||
Then you can increase the query timeout solely for your session:
|
||||
|
||||
|
||||
@@ -37,15 +37,15 @@ limit 100;
|
||||
|
||||
They tend to be caused by one of the following factors.
|
||||
|
||||
### Attempted to access a forbidden schema
|
||||
## Attempted to access a forbidden schema
|
||||
|
||||
API roles cannot access certain schemas, most notably `auth` and `vault`. This restriction extends to Foreign Data Wrappers relying on `vault`. While you can bypass it using a [security definer function](/docs/guides/database/functions?queryGroups=language&language=sql&queryGroups=example-view&example-view=sql#security-definer-vs-invoker), these schemas are intentionally restricted for security reasons.
|
||||
|
||||
### Attempted to access a custom schema
|
||||
## Attempted to access a custom schema
|
||||
|
||||
If you created a custom schema, you will have to give the Database API permission to query it. Follow our [Using Custom Schemas guide](/docs/guides/api/using-custom-schemas) for more directions.
|
||||
|
||||
### Missing table-level privileges
|
||||
## Missing table-level privileges
|
||||
|
||||
If you see an error like `permission denied for table your_table`, the querying role may not have the required privilege for the operation.
|
||||
|
||||
@@ -79,10 +79,10 @@ For more information, see [Securing your API](/docs/guides/api/securing-your-api
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Configured column-level restrictions
|
||||
## Configured column-level restrictions
|
||||
|
||||
If you've set column-based access in the [Dashboard](/dashboard/project/_/database/column-privileges) or via SQL, queries will fail with a `42501` error when accessing restricted columns. This includes using `select *`, as it expands to include forbidden columns.
|
||||
|
||||
### RLS:
|
||||
## RLS:
|
||||
|
||||
If the anon or authenticated roles attempt to UPDATE or INSERT values without the necessary RLS permissions, Postgres will return a 42501 error.
|
||||
@@ -7,7 +7,7 @@ keywords = [ "prepared", "statements", "transaction", "mode", "disable" ]
|
||||
database_id = "04801b69-e7eb-4f40-8d41-81110397bbc2"
|
||||
---
|
||||
|
||||
### It is important to note that although the direct connections and Supavisor in session mode support prepared statements, Supavisor in transaction mode does not.
|
||||
## It is important to note that although the direct connections and Supavisor in session mode support prepared statements, Supavisor in transaction mode does not.
|
||||
|
||||
## How to disable prepared statements for Supavisor in transaction mode
|
||||
|
||||
|
||||
+2
-2
@@ -164,7 +164,7 @@ from
|
||||
|
||||
## Finding errors
|
||||
|
||||
#### API level errors
|
||||
### API level errors
|
||||
|
||||
The `metadata.request.url` contains PostgREST formatted queries.
|
||||
|
||||
@@ -213,7 +213,7 @@ where
|
||||
|
||||
PostgREST has an [error reference table](https://postgrest.org/en/v12/references/errors.html) that you can use to interpret status codes.
|
||||
|
||||
#### Database-level errors
|
||||
### Database-level errors
|
||||
|
||||
However, some errors that are reported through the Database API occur at the Postgres level. If it is not clear which error occurred you should reference the timestamp of the error and try to see if you can find it in the Postgres logs.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ An internal 504 from an Edge Function means the function failed to initiate a re
|
||||
|
||||
As of now, this limit cannot be increased. If your function always needs more time than allowed, skip to [When optimization isn't enough](#when-optimization-is-not-enough) section. Otherwise, follow the steps below to speed up response times.
|
||||
|
||||
### Step 1: Identifying slow Functions
|
||||
## Step 1: Identifying slow Functions
|
||||
|
||||
You can filter for 504 events in the Log Explorer with the below [query](/dashboard/project/_/logs/explorer?q=select%0A++cast%28timestamp+as+datetime%29+as+timestamp%2C%0A++req.pathname%2C%0A++res.status_code%2C%0A++metadata.execution_time_ms%0Afrom%0A++function_edge_logs%0A++cross+join+UNNEST%28metadata%29+as+metadata%0A++cross+join+UNNEST%28metadata.request%29+as+req%0A++cross+join+UNNEST%28metadata.response%29+as+res%0Awhere+res.status_code+%3D+504%0Alimit+20%3B):
|
||||
|
||||
@@ -53,7 +53,7 @@ limit 20;
|
||||
|
||||
Once candidate functions are identified, you can investigate more thoroughly.
|
||||
|
||||
### Step 2: Investigating slow Functions
|
||||
## Step 2: Investigating slow Functions
|
||||
|
||||
Add `console.time` labels around suspicious sections to pinpoint where time is being spent:
|
||||
|
||||
@@ -76,11 +76,11 @@ Common culprits:
|
||||
- External APIs that are throttling or rate-limiting you
|
||||
- Loops without a clear escape condition
|
||||
|
||||
### Step 3: Optimize
|
||||
## Step 3: Optimize
|
||||
|
||||
The below suggestions are some strategies you can pursue to reduce execution times.
|
||||
|
||||
#### Parallelizing requests
|
||||
### Parallelizing requests
|
||||
|
||||
If requests are independent of one another, rather than calling them sequentially, you can speed up operations by calling them in parallel with [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
|
||||
|
||||
@@ -96,15 +96,15 @@ const [resultA, resultB] = await Promise.all([
|
||||
])
|
||||
```
|
||||
|
||||
#### Splitting up logic
|
||||
### Splitting up logic
|
||||
|
||||
The Edge Function may be doing more than it needs to. It may be better to split up it's logic into multiple parts that can be called individually and run for shorter periods.
|
||||
|
||||
#### Use background tasks [utilize-background-tasks]
|
||||
### Use background tasks [utilize-background-tasks]
|
||||
|
||||
You can initiate functions in a background task to be handled independently of the request/response handler. The process is outlined in the [Background Task docs](/docs/guides/functions/background-tasks)
|
||||
|
||||
#### Offload work to the client or an external service
|
||||
### Offload work to the client or an external service
|
||||
|
||||
Instead of managing all operations within the function itself, there may be an external API that can execute jobs faster and then send back results. Alternatively, you may be able to offload some processing to the requester rather than doing everything within the function itself.
|
||||
|
||||
@@ -143,7 +143,7 @@ group by req.pathname, res.status_code
|
||||
limit 10;
|
||||
```
|
||||
|
||||
### When optimization is not enough
|
||||
## When optimization is not enough
|
||||
|
||||
Edge Functions have a hard runtime ceiling that cannot be raised. If your use case genuinely requires more, consider:
|
||||
|
||||
|
||||
+4
-4
@@ -7,7 +7,7 @@ database_id = "23668386-7a72-44ff-a412-4cd8a005fa18"
|
||||
|
||||
When facing high CPU utilization, slow query performance, and an `ERROR: must be a superuser to terminate superuser process` message regarding an autovacuum, it indicates that a critical, non-terminable autovacuum operation is running on your Postgres database. This guide explains why this happens and what steps you can take.
|
||||
|
||||
### **Core Postgres concepts**
|
||||
## Core Postgres concepts
|
||||
|
||||
To understand this issue, it's essential to grasp a few core Postgres concepts:
|
||||
|
||||
@@ -25,7 +25,7 @@ Every transaction in Postgres is assigned a unique Transaction ID (XID). These X
|
||||
|
||||
To prevent this critical issue, Postgres initiates a special autovacuum operation: the **"wraparound prevention vacuum."**
|
||||
|
||||
### **Understanding the problem: A critical autovacuum**
|
||||
## Understanding the problem: A critical autovacuum
|
||||
|
||||
When you encounter the `ERROR: must be a superuser to terminate superuser process` associated with an autovacuum marked "to prevent wraparound," it signifies that this mandatory, system-critical operation is underway.
|
||||
|
||||
@@ -38,7 +38,7 @@ When you encounter the `ERROR: must be a superuser to terminate superuser proces
|
||||
**Why is it running?**
|
||||
This situation often arises in large, high-write tables (e.g., `your_table`, which might be hundreds of GBs in size and contain hundreds of millions of rows) that accumulate dead tuples rapidly. When the transaction ID age of the table approaches a critical threshold, Postgres automatically triggers this emergency autovacuum. For instance, if a table has millions of rows and over a million dead rows, exceeding its configured `autovacuum_vacuum_scale_factor` (e.g., 0.2), a regular autovacuum might initiate. However, if the XID age continues to increase, the system prioritizes the wraparound prevention vacuum to safeguard data integrity.
|
||||
|
||||
### **Mitigating performance impact during a critical autovacuum**
|
||||
## Mitigating performance impact during a critical autovacuum
|
||||
|
||||
Since the wraparound prevention autovacuum cannot be stopped, the best approach is to provide the database with sufficient resources to complete the operation as efficiently as possible.
|
||||
|
||||
@@ -52,7 +52,7 @@ Since the wraparound prevention autovacuum cannot be stopped, the best approach
|
||||
- **Why it helps:** Autovacuum is an I/O-intensive operation, involving a lot of reading and writing. Higher disk performance can significantly speed up the process.
|
||||
- **Considerations:** Cloud providers may limit the number of disk modifications (e.g., up to four in a rolling 24-hour window). You can start a new modification immediately after the previous one finishes, provided you have not exceeded this rolling 24-hour quota.
|
||||
|
||||
### **Monitoring progress and future prevention**
|
||||
## Monitoring progress and future prevention
|
||||
|
||||
**Monitoring the Current Autovacuum:**
|
||||
You can monitor the progress of the active autovacuum processes using the `pg_stat_progress_vacuum` view:
|
||||
|
||||
+8
-8
@@ -9,9 +9,9 @@ database_id = "e7671f20-2639-442e-9df9-4f6fa3766598"
|
||||
|
||||
> For the curious: [here is a list of all built-in indexes in Postgres](https://www.postgresql.org/docs/current/indexes-types.html)
|
||||
|
||||
### Postgres internals
|
||||
## Postgres internals
|
||||
|
||||
#### How an index is chosen
|
||||
### How an index is chosen
|
||||
|
||||
Postgres, internally, contains a few components that manage query execution:
|
||||
|
||||
@@ -98,11 +98,11 @@ To reset statistics within the database, you can use the following query:
|
||||
select pg_stat_reset();
|
||||
```
|
||||
|
||||
### Complex or composite indexes
|
||||
## Complex or composite indexes
|
||||
|
||||
> For a more complete rundown, check the [Postgres Official Docs](https://www.postgresql.org/docs/current/indexes-multicolumn.html)
|
||||
|
||||
#### Multi-column indexes
|
||||
### Multi-column indexes
|
||||
|
||||
If you make independent indexes on multiple columns, Postgres will likely use each of them independently to find the relevant rows and then combine the results together.
|
||||
|
||||
@@ -118,7 +118,7 @@ from test2
|
||||
where major = constant and minor = constant;
|
||||
```
|
||||
|
||||
#### Ordered indexes
|
||||
### Ordered indexes
|
||||
|
||||
If you're using an ORDER BY clause, [indexes can also be pre-sorted by DESC/ASC](https://www.postgresql.org/docs/current/indexes-ordering.html) for better performance.
|
||||
|
||||
@@ -127,7 +127,7 @@ If you're using an ORDER BY clause, [indexes can also be pre-sorted by DESC/ASC]
|
||||
CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST);
|
||||
```
|
||||
|
||||
#### Functional indexes
|
||||
### Functional indexes
|
||||
|
||||
Although not as common, indexes can also be leveraged against modified values, such as when using a LOWER function:
|
||||
|
||||
@@ -139,7 +139,7 @@ create index test1_lower_col1_idx on test1 (lower(col1));
|
||||
select * from test1 where lower(col1) = 'value';
|
||||
```
|
||||
|
||||
#### Covering indexes
|
||||
### Covering indexes
|
||||
|
||||
Indexes contain pointers to a specific row, but you could instruct an index to hold a copy of a column's value for even faster retrieval. These are known as `covering` indexes. Because maintaining a copy is storage intensive, you should avoid using it for values with large data footprints.[ FULL VIDEO ON TOPIC](https://www.youtube.com/watch?v=bBu_V8CfWgM)
|
||||
|
||||
@@ -147,7 +147,7 @@ Indexes contain pointers to a specific row, but you could instruct an index to h
|
||||
CREATE INDEX a_b_idx ON x (a,b) INCLUDE (c);
|
||||
```
|
||||
|
||||
#### Indexes on JSONB
|
||||
### Indexes on JSONB
|
||||
|
||||
Although a GIN/GIST index can be used to index entire JSONB bodies, you can also target only specific Key-values with standard BTREE indexes:
|
||||
|
||||
|
||||
@@ -54,17 +54,17 @@ SHOW max_connections;
|
||||
|
||||
**Three** factors must be taken into consideration when adjusting the direct connection limit:
|
||||
|
||||
#### Process schedulers and Postgres internals
|
||||
### Process schedulers and Postgres internals
|
||||
|
||||
Allowing too many direct connections in your database can overburden Postgres schedulers and other internal modules. This will result in a noticeable decrease in query throughput, despite having more connections available. EnterpriseDB wrote a wonderful [article](https://www.enterprisedb.com/postgres-tutorials/why-you-should-use-connection-pooling-when-setting-maxconnections-postgres) that outlines some of the considerations.
|
||||
|
||||
The default connection values are set based on a solid understanding of Postgres architecture, and straying too far from them is _likely_ to hinder performance. However, with some experimentation, you might discover a value better suited to your specific needs. Still, unless there's a compelling reason to adjust the setting, it's generally advisable to stick with the defaults or change the values judiciously.'
|
||||
|
||||
#### Memory
|
||||
### Memory
|
||||
|
||||
> If you do not know how to monitor memory and CPU with Supabase Grafana, [check here](https://github.com/orgs/supabase/discussions/27141).
|
||||
|
||||
##### Each direct connection is a running process that will consume active memory
|
||||
#### Each direct connection is a running process that will consume active memory
|
||||
|
||||
This is a Grafana Chart of unhealthy memory usage:
|
||||
|
||||
@@ -92,7 +92,7 @@ select
|
||||
) || ' * ' || current_setting('maintenance_work_mem') || ')) / ' || current_setting('work_mem');
|
||||
```
|
||||
|
||||
#### CPU
|
||||
### CPU
|
||||
|
||||
The below chart is an example of what can occur to the CPU if 100s of connections are inappropriately opened/closed every second or many CPU intensive queries are run in parallel
|
||||
|
||||
|
||||
+10
-10
@@ -191,7 +191,7 @@ Queries can use complex syntax, so it is often helpful to isolate by referenced
|
||||
|
||||
All failed queries, including those from PostgREST, Auth, and external libraries (e.g., Prisma) are logged with helpful error messages for debugging.
|
||||
|
||||
##### Server/Role mapping
|
||||
#### Server/Role mapping
|
||||
|
||||
API servers have assigned database roles for connecting to the database:
|
||||
|
||||
@@ -257,7 +257,7 @@ limit 100;
|
||||
|
||||
## Logging for compliance and security
|
||||
|
||||
#### Customized object and role activity logging
|
||||
### Customized object and role activity logging
|
||||
|
||||
> ⚠️ NOTE: This is specifically designated for those using the `postgres` role or [custom roles](/docs/guides/database/postgres/roles) to interact with their database. Those using the Database REST API should reference the [Database API Logging Guide](https://github.com/orgs/supabase/discussions/22849) instead.
|
||||
|
||||
@@ -279,7 +279,7 @@ where
|
||||
parsed.user_name = 'API_role'
|
||||
```
|
||||
|
||||
#### Filtering by IP
|
||||
### Filtering by IP
|
||||
|
||||
> If you are connecting from a known, limited range of IP addresses, you should enable [network restrictions](/docs/guides/platform/network-restrictions).
|
||||
|
||||
@@ -341,7 +341,7 @@ where
|
||||
|
||||
> WARNING: lenient settings can lead to over-logging, impacting database performance while creating noise in the logs.
|
||||
|
||||
##### Severity levels
|
||||
#### Severity levels
|
||||
|
||||
The `log_min_messages` variable determines what is severe enough to log. Here are the severity thresholds from the [Postgres docs](https://www.postgresql.org/docs/current/runtime-config-logging.html).
|
||||
|
||||
@@ -365,7 +365,7 @@ alter role postgres set log_min_messages = '<NEW VALUE>';
|
||||
show log_min_messages; -- default WARNING
|
||||
```
|
||||
|
||||
##### Configuring queries logged
|
||||
#### Configuring queries logged
|
||||
|
||||
By default, only failed queries are logged. The [PGAudit extension](/docs/guides/database/extensions/pgaudit) extends Postgres's built-in logging abilities. It can be used to selectively track all queries in your database by:
|
||||
|
||||
@@ -374,25 +374,25 @@ By default, only failed queries are logged. The [PGAudit extension](/docs/guides
|
||||
- database object
|
||||
- entire database
|
||||
|
||||
##### Logging within database functions
|
||||
#### Logging within database functions
|
||||
|
||||
To track or debug functions, logging can be configured by following the [function debugging guide](/docs/guides/database/functions#general-logging)
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
##### How to join different log tables
|
||||
### How to join different log tables
|
||||
|
||||
No, log tables are independent from each other and do not share any primary/foreign key relations for joining.
|
||||
|
||||
##### How to download logs
|
||||
### How to download logs
|
||||
|
||||
At the moment, the way to download logs is through the Log Dashboard as a CSV
|
||||
|
||||
##### What is logged?
|
||||
### What is logged?
|
||||
|
||||
To see the default types of events that are logged, you can check this [guide](https://gist.github.com/TheOtherBrian1/991d32c2b00dbc75d29b80d4cdf41aa7).
|
||||
|
||||
#### Other resources:
|
||||
### Other resources:
|
||||
|
||||
- [Regex for filtering logs](https://github.com/orgs/supabase/discussions/22640)
|
||||
- [Debugging with the DB API logs](https://github.com/orgs/supabase/discussions/22849)
|
||||
|
||||
+8
-8
@@ -13,7 +13,7 @@ Here are the steps for you to migrate your application from the `auth-helpers` p
|
||||
|
||||
Depending on your implementation, you may ignore some parts of this documentation and use your own implementation (i.e. using API routes vs. Server Actions). What's important is you replace the clients provided by `auth-helpers` with the utility functions created using clients provided by `@supabase/ssr`.
|
||||
|
||||
### 1. Uninstall Supabase Auth helpers and install the Supabase SSR package
|
||||
## 1. Uninstall Supabase Auth helpers and install the Supabase SSR package
|
||||
|
||||
It's important that you don't use both `auth-helpers-nextjs` and `@supabase/ssr` packages in the same application to avoid running into authentication issues.
|
||||
|
||||
@@ -22,7 +22,7 @@ npm uninstall @supabase/auth-helpers-nextjs @supabase/supabase-js
|
||||
npm install @supabase/ssr @supabase/supabase-js
|
||||
```
|
||||
|
||||
### 2. Create the library functions to create Supabase clients
|
||||
## 2. Create the library functions to create Supabase clients
|
||||
|
||||
```
|
||||
// lib/supabase/client.ts
|
||||
@@ -136,7 +136,7 @@ export async function updateSession(request: NextRequest) {
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Replace your proxy.ts file
|
||||
## 3. Replace your proxy.ts file
|
||||
|
||||
```
|
||||
// proxy.ts
|
||||
@@ -162,7 +162,7 @@ export const config = {
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Create your server actions to handle login and sign up
|
||||
## 4. Create your server actions to handle login and sign up
|
||||
|
||||
```
|
||||
// app/login/actions.ts
|
||||
@@ -215,7 +215,7 @@ export async function signup(formData: FormData) {
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Use the server actions in your login page UI
|
||||
## 5. Use the server actions in your login page UI
|
||||
|
||||
```
|
||||
// app/login/page.tsx
|
||||
@@ -236,7 +236,7 @@ export default function LoginPage() {
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Client components
|
||||
## 6. Client components
|
||||
|
||||
```
|
||||
'use client';
|
||||
@@ -258,7 +258,7 @@ export default async function Page() {
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Server components
|
||||
## 7. Server components
|
||||
|
||||
```
|
||||
// replace
|
||||
@@ -282,7 +282,7 @@ export default async function Page() {
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Route handlers
|
||||
## 8. Route handlers
|
||||
|
||||
```
|
||||
// replace
|
||||
|
||||
@@ -17,7 +17,7 @@ Symptoms of HTTP API issues include:
|
||||
- 5xx response codes
|
||||
- High response times
|
||||
|
||||
### Under-provisioned resources
|
||||
## Under-provisioned resources
|
||||
|
||||
The most common class of issues that causes HTTP timeouts and 5xx response codes is the under-provisioning of resources for your project. This can cause your project to be unable to service the traffic it is receiving.
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ database_id = "7d755701-747f-4c3a-b8be-236c5518e4eb"
|
||||
|
||||
> Building an index without the `CONCURRENTLY` modifier will lock the table, but it will also increase build times. For general advice about indexes, check out this [guide](https://github.com/orgs/supabase/discussions/22449).
|
||||
|
||||
### **To speed up queries, it is ideal to create an HSNW index on your embedded column**
|
||||
## **To speed up queries, it is ideal to create an HSNW index on your embedded column**
|
||||
|
||||
The general structure for creating an HNSW index follows this pattern:
|
||||
|
||||
|
||||
+2
-2
@@ -25,13 +25,13 @@ The CPU chart shows 4 distinct metrics of interest:
|
||||
|
||||
As the CPU peaks towards 100%, queries and database tasks will begin to throttle, as they won't have enough time or access to the CPU.
|
||||
|
||||
#### Other useful Supabase Grafana guides:
|
||||
### Other useful Supabase Grafana guides:
|
||||
|
||||
- [Connections](https://github.com/orgs/supabase/discussions/27141)
|
||||
- [Disk](https://github.com/orgs/supabase/discussions/27003)
|
||||
- [Memory](https://github.com/orgs/supabase/discussions/27021)
|
||||
|
||||
#### Optimizing
|
||||
### Optimizing
|
||||
|
||||
1. [Optimize your queries](/docs/guides/database/query-optimization).
|
||||
2. [Add indexes](https://github.com/orgs/supabase/discussions/22449) if possible.
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ Other useful Supabase Grafana guides:
|
||||
- [Memory](https://github.com/orgs/supabase/discussions/27021)
|
||||
- [CPU](https://github.com/orgs/supabase/discussions/27022)
|
||||
|
||||
### Esoteric factors
|
||||
## Esoteric factors
|
||||
|
||||
**Webhooks**:
|
||||
Supabase webhooks use the pg_net extension to handle requests. The `net.http_request_queue` table isn't indexed to keep write costs low. However, if you upload millions of rows to a webhook-enabled table in rapid succession, it can significantly increase the read costs for the extension.
|
||||
|
||||
@@ -7,7 +7,7 @@ database_id = "c5dae428-8dd0-4879-b312-df7f7da25986"
|
||||
|
||||
Branching in Supabase (Branching 2.0) relies on the current migration files in your project—**not** a schema dump—when creating environments from `main`. This means if your `main` branch lacks migration history, branching will not fully capture your schema. This is a known limitation highlighted in the [Branching 2.0 documentation](/blog/branching-2-0#current-limitations). Follow the steps below to generate, synchronize, and repair your migration history for smooth branching.
|
||||
|
||||
#### 1. Prerequisites: Prepare local Supabase environment
|
||||
## 1. Prerequisites: Prepare local Supabase environment
|
||||
|
||||
- If you do not have a local environment set up already, follow the Supabase local development getting started guide:
|
||||
- [Running Supabase Locally](/docs/guides/local-development/cli/getting-started).
|
||||
@@ -21,7 +21,7 @@ supabase start
|
||||
|
||||
---
|
||||
|
||||
#### 2. Pull remote schema into migrations
|
||||
## 2. Pull remote schema into migrations
|
||||
|
||||
With your project linked, run:
|
||||
|
||||
@@ -33,7 +33,7 @@ This command generates a migration file in your `supabase/migrations` folder whi
|
||||
|
||||
---
|
||||
|
||||
#### 3. Sync remote migration history
|
||||
## 3. Sync remote migration history
|
||||
|
||||
Upon running the above command, the Supabase CLI will typically prompt with:
|
||||
|
||||
@@ -54,12 +54,12 @@ Run the exact repair command provided, replacing the timestamp as instructed (ex
|
||||
|
||||
---
|
||||
|
||||
#### 4. Proceed with Branching
|
||||
## 4. Proceed with Branching
|
||||
|
||||
Once your migration history is up to date, continue to use branching features as normal. Each new branch will now inherit the correct migrations from your `main` branch.
|
||||
|
||||
---
|
||||
|
||||
#### Additional tips
|
||||
## Additional tips
|
||||
|
||||
If further issues arise (such as schema drift or migration mismatches), review the [troubleshooting documentation](/docs/guides/deployment/branching/troubleshooting#migration-issues), and consider manual repair with [`supabase migration repair`](/docs/reference/cli/supabase-migration-repair).
|
||||
+2
-2
@@ -15,11 +15,11 @@ As the initial step in debugging not-delivered emails, check your project's [Aut
|
||||
|
||||
Once handed over to the email provider, Supabase has no control over email delivery. There can be multiple reasons why emails do not reach the user's inbox.
|
||||
|
||||
#### 1. Issues with the email provider.
|
||||
## 1. Issues with the email provider.
|
||||
|
||||
The email provider's logs are the next place to look for email delivery issues. There are cases where the email provider blocks the delivery due to past bounced-back emails. Some email providers maintain a suppression list for not sending emails due to several reasons. You can read more about it here - https://sendgrid.com/en-us/blog/what-is-a-suppression-list
|
||||
|
||||
#### 2. Issues with the user's email server
|
||||
## 2. Issues with the user's email server
|
||||
|
||||
Many email firewalls maintain a denylist of IPs and domain names for security reasons and as spam filters. Sometimes, they block incoming emails from unknown addresses with certain keywords such as password reset, verification link, etc. In these cases, ask the user to check with their email server admin to see if they are blocking your email domain or quarantining the incoming emails. If you use the default provider, the email domain is `supabase.io`. Some information on email firewalls are available here - https://mailchimp.com/help/about-email-firewalls/.
|
||||
|
||||
|
||||
+3
-3
@@ -14,15 +14,15 @@ http_status_code = 500
|
||||
|
||||
A 500 error in Auth typically indicates an issue with an external dependency, such as your database or SMTP provider, rather than with Auth itself. This guide will help you explore the Auth logs to identify the underlying cause.
|
||||
|
||||
#### Prerequisites
|
||||
### Prerequisites
|
||||
|
||||
##### Open the log explorer
|
||||
#### Open the log explorer
|
||||
|
||||
Ensure you have access to the [Dashboard's Log Explorer](/dashboard/project/_/logs/explorer) and set the time range appropriately:
|
||||
|
||||

|
||||
|
||||
##### Improving log readability
|
||||
#### Improving log readability
|
||||
|
||||
Logs are displayed in a table format, which can be challenging to read. Double-clicking on a row will expand it for easier viewing:
|
||||
|
||||
|
||||
+9
-9
@@ -4,7 +4,7 @@ topics = [ "database", "supavisor" ]
|
||||
keywords = []
|
||||
---
|
||||
|
||||
### Key technical terms
|
||||
## Key technical terms
|
||||
|
||||
**Transaction Pooling**
|
||||
A connection management method used by tools like Supavisor or PgBouncer. Instead of giving every client a dedicated, permanent connection to the database, the pooler maintains a small set of "backend connections." It lends one of these connections to a client for the duration of a single transaction, then immediately takes it back to give to another client.
|
||||
@@ -17,29 +17,29 @@ That backend connection has _state_. Postgres connections carry settings like ti
|
||||
|
||||
---
|
||||
|
||||
### Understanding the problem: The "sticky" state
|
||||
## Understanding the problem: The "sticky" state
|
||||
|
||||
When you encounter the error `cannot execute UPDATE in a read-only transaction` while using a transaction pooler (typically on port 6543), even when you have verified that the connection is made to the primary database and the database itself is not in read-only mode (check with `SHOW default_transaction_read_only;` or `SELECT pg_is_in_recovery();` using a direct connection on port 5432), it signifies that a backend connection has been unintentionally locked into a read-only state.
|
||||
|
||||
**Note:** If your database is in read-only mode (for example, due to exceeding disk space limits), you can review this guide: [Database Size and Read-Only Mode](/docs/guides/platform/database-size#read-only-mode). The remainder of this guide addresses a different issue specific to transaction pooling.
|
||||
|
||||
#### The cause: Connection contamination
|
||||
### The cause: Connection contamination
|
||||
|
||||
In transaction pooling mode, reset behavior is intentionally limited for performance, so session state can persist unless explicitly reset. If a client, script, or automated task changes a session-level setting, that setting "sticks" to the backend connection.
|
||||
|
||||
When that backend connection is returned to the pool, the next client to use it inherits that exact state. If a previous script set the connection to "read-only" for safety and failed to reset it, any subsequent application attempt to perform an `UPDATE` or `INSERT` using that same backend will fail.
|
||||
|
||||
#### Why is the error sporadic?
|
||||
### Why is the error sporadic?
|
||||
|
||||
The error appears intermittent because it only occurs when your application is randomly assigned a "contaminated" backend connection from the pool. Other connections in the same pool may still be in the default read-write state, leading to a confusing mix of successful and failed requests.
|
||||
|
||||
---
|
||||
|
||||
### Step-by-step resolution
|
||||
## Step-by-step resolution
|
||||
|
||||
To resolve this issue, you must identify and remove any commands that modify the session state globally rather than locally.
|
||||
|
||||
#### 1. Audit application and scripts
|
||||
### 1. Audit application and scripts
|
||||
|
||||
Search your application code, migration scripts, and maintenance tasks for the following session-level commands:
|
||||
|
||||
@@ -48,7 +48,7 @@ Search your application code, migration scripts, and maintenance tasks for the f
|
||||
|
||||
Even if these commands are used in secondary scripts (like data exports or safety-first maintenance tasks) and not the main application, they can still contaminate the pool used by the main application.
|
||||
|
||||
#### 2. Implement "safe" settings
|
||||
### 2. Implement "safe" settings
|
||||
|
||||
If you need to execute a read-only transaction for safety, use transaction-level commands that only affect the current transaction and do not persist on the backend connection.
|
||||
|
||||
@@ -60,7 +60,7 @@ If you have existing scripts that use session-level settings and cannot be immed
|
||||
- **Temporary workaround:** Ensure they explicitly reset the state before closing the connection with `SET default_transaction_read_only = off;`
|
||||
- **Best approach:** Connect directly to port 5432 (bypassing the pooler) for scripts requiring special session states
|
||||
|
||||
#### 3. Connection string verification
|
||||
### 3. Connection string verification
|
||||
|
||||
Ensure your application is using the intended pooler.
|
||||
|
||||
@@ -69,6 +69,6 @@ Ensure your application is using the intended pooler.
|
||||
|
||||
---
|
||||
|
||||
### Best practices for transaction pooling
|
||||
## Best practices for transaction pooling
|
||||
|
||||
- **Use Dedicated Connections for Maintenance:** If a script requires a specific session state (like a long-running read-only export), connect directly to the database (port 5432) rather than using the transaction pooler (port 6543). This prevents maintenance settings from leaking into the application's connection pool.%
|
||||
+4
-4
@@ -7,7 +7,7 @@ keywords = [ "hostname", "ip", "ipv4", "ipv6" ]
|
||||
database_id = "c89147f8-a66a-4c04-a1a7-45442fd7f2ee"
|
||||
---
|
||||
|
||||
### Finding your database hostname
|
||||
## Finding your database hostname
|
||||
|
||||
Your database's hostname is crucial for establishing a direct connection. It resolves to the underlying IP address of your database.
|
||||
|
||||
@@ -17,7 +17,7 @@ Example Hostname: `db.zcjtzmeifsoteyjytnbc.supabase.co`
|
||||
|
||||

|
||||
|
||||
### Managing your IP address
|
||||
## Managing your IP address
|
||||
|
||||
To determine your current IP address, you can use an [IP address lookup](https://whatismyipaddress.com/hostname-ip) website or the terminal command:
|
||||
|
||||
@@ -26,14 +26,14 @@ To determine your current IP address, you can use an [IP address lookup](https:/
|
||||
|
||||
Example IPv6 Address: `2a05:d014:1c06:5f0c:d7a9:8616:bee2:30df`
|
||||
|
||||
### IPv6 address
|
||||
## IPv6 address
|
||||
|
||||
Upon project creation, a static IPv6 address is assigned. However, it's essential to understand that this IPv6 address can change due to specific actions:
|
||||
|
||||
- When a project is paused or resumed.
|
||||
- During database version upgrades.
|
||||
|
||||
### IPv4 address
|
||||
## IPv4 address
|
||||
|
||||
Opting for the static [IPv4 add-on](/docs/guides/platform/ipv4-address) provides a more stable connection address. The IPv4 address remains constant unless:
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ keywords = [ "rls", "sql", "policy" ]
|
||||
database_id = "5b8a5115-f81a-4a1f-bcc3-fdc2a2672e80"
|
||||
---
|
||||
|
||||
### Basic summary
|
||||
## Basic summary
|
||||
|
||||
Row-Level Security (RLS) Policy: A `WHERE` or `CHECK` condition applied automatically to database queries
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ database_id = "46bab0a2-9780-4e4f-99f5-fcc9fa51c496"
|
||||
|
||||
We want to clarify and provide reassurance on this topic.
|
||||
|
||||
### Security overview:
|
||||
## Security overview:
|
||||
|
||||
Enabling anonymous sign-ins on your project does not reduce its security. Here's why:
|
||||
|
||||
@@ -17,7 +17,7 @@ Enabling anonymous sign-ins on your project does not reduce its security. Here's
|
||||
- Security Policies: All role-based security policies (RLS) applicable to regular users also apply to anonymous users.
|
||||
- Identity Verification Measures: Even though anonymous users do not initially provide an email or phone number, the security of your project remains robust. But to prevent misuse, we recommend implementing additional security measure such as [CAPTCHA](/docs/guides/auth/auth-captcha): to ensure that interactions are genuinely human.
|
||||
|
||||
### Practical use cases:
|
||||
## Practical use cases:
|
||||
|
||||
- Demo Mode: You can enable users to try out your product in a demo mode without full account creation.
|
||||
- Feature Restrictions: You can limit certain actions (like posting public content) to users who sign up with more identifiable information (e.g., Google or Apple sign-ins), while still allowing anonymous users to explore your app.
|
||||
|
||||
+7
-7
@@ -14,11 +14,11 @@ The internet uses a system called the Internet Protocol (IP) to route communicat
|
||||
- **IPv4**: Introduced in 1980, it's the original version.
|
||||
- **IPv6**: Launched in 1999, it offers a much larger address space and is the preferred future-proof option.
|
||||
|
||||
#### Supabase and IPv6
|
||||
### Supabase and IPv6
|
||||
|
||||
All Supabase databases provide a direct connection string that maps to an IPv6 address.
|
||||
|
||||
#### Working with IPv6 incompatible hosts
|
||||
### Working with IPv6 incompatible hosts
|
||||
|
||||
Here are your options if your server platform doesn't support IPv6:
|
||||
|
||||
@@ -28,7 +28,7 @@ Here are your options if your server platform doesn't support IPv6:
|
||||
|
||||
> Note: the IPv4 Add-On costs <Price price="0.0055" /> an hour, which equates to ~<Price price="4.00" /> if left on for a full month (~720 hours)
|
||||
|
||||
#### Checking IPv6 support
|
||||
### Checking IPv6 support
|
||||
|
||||
The majority of services are IPv6 compatible. However, there are a few prominent ones that only accept IPv4 connections:
|
||||
|
||||
@@ -45,7 +45,7 @@ curl -6 https://ifconfig.co/ip
|
||||
|
||||
If the command returns an IPv6 address, the network is IPv6 compatible.
|
||||
|
||||
#### Finding your database's IP address
|
||||
### Finding your database's IP address
|
||||
|
||||
To determine your current IP address, you can use an IP address [lookup website](https://whatismyipaddress.com/hostname-ip) or the terminal command:
|
||||
|
||||
@@ -57,7 +57,7 @@ This command queries the domain name servers to find the IP address of the given
|
||||
|
||||
Example IPv6 Address: `2a05:d014:1c06:5f0c:d7a9:8616:bee2:30df`
|
||||
|
||||
#### Identifying your connections
|
||||
### Identifying your connections
|
||||
|
||||
The pooler and direct connection strings can be found on the dashboard by clicking [Connect](/dashboard/project/_?showConnect=true).
|
||||
|
||||
@@ -68,14 +68,14 @@ The pooler and direct connection strings can be found on the dashboard by clicki
|
||||
postgresql://postgres:[YOUR-PASSWORD]@db.ajrbwkcuthywfihaarmflo.supabase.co:5432/postgres
|
||||
```
|
||||
|
||||
##### Supavisor in transaction mode (port 6543)
|
||||
#### Supavisor in transaction mode (port 6543)
|
||||
|
||||
```sh
|
||||
# Example transaction string
|
||||
postgresql://postgres.ajrbwkcuthywddfihrmflo:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
|
||||
```
|
||||
|
||||
##### Supavisor in session mode (port 5432)
|
||||
#### Supavisor in session mode (port 5432)
|
||||
|
||||
```sh
|
||||
# Example session string
|
||||
|
||||
@@ -50,7 +50,7 @@ Optimizing:
|
||||
5. [Remove bloat](/docs/reference/cli/supabase-inspect-db): Bloat can fragment data across pages, causing redundant data to be pulled from disk.
|
||||
6. Table refactoring: Split tables to isolate columns that are less frequently accessed, so they are not redundantly pulled into memory while accessing hotter data
|
||||
|
||||
### Other useful Supabase Grafana guides:
|
||||
## Other useful Supabase Grafana guides:
|
||||
|
||||
- [Connections](https://github.com/orgs/supabase/discussions/27141)
|
||||
- [Disk](https://github.com/orgs/supabase/discussions/27003)
|
||||
|
||||
@@ -7,7 +7,7 @@ keywords = [ "pooler", "connections", "supavisor", "database" ]
|
||||
database_id = "f252ba39-e540-462b-868f-42eb31a5d40c"
|
||||
---
|
||||
|
||||
### What problems do poolers solve?
|
||||
## What problems do poolers solve?
|
||||
|
||||
Postgres stands out from other databases by opting to create a new process, not a new thread, for each direct connection. While this design choice brings [numerous benefits](https://www.postgresql.org/message-id/1098894087.31930.62.camel@localhost.localdomain), it introduces a startup penalty for new connections. Moreover, connections are more memory-intensive and can strain Postgres's internal schedulers, limiting the sustainable number that can be formed. Resultingly, developers must be mindful of how they allocate the resource.
|
||||
|
||||
@@ -15,11 +15,11 @@ When a client (backend server) connects to Postgres, the connection is stateful
|
||||
|
||||
Postgres's shortcomings are particularly evident when handling transient servers, like edge functions. They not only hoard connections for brief queries but also aggressively open and close connections, straining the database.
|
||||
|
||||
### How do poolers solve the problem?
|
||||
## How do poolers solve the problem?
|
||||
|
||||
A pooler is ultimately a load balancer for database connections. It maintains several hot connections that it triages to clients. This reduces the startup cost of creating a new process on Postgres. The pooler can also more efficiently manage a database's finite connections by only allowing clients to access them when they need to execute a query (A.K.A. transaction mode).
|
||||
|
||||
### Are poolers necessary?
|
||||
## Are poolers necessary?
|
||||
|
||||
All database connection libraries, such as Prisma, SQLAlchemy, and Postgres.js have built-in poolers. These are known as application-side poolers and they are fundamental for sustainable connection management. Most libraries have default pool sizes that may need to be changed for specific workloads. As an example, most edge/serverless functions are called to service a single user's request. They usually require significantly fewer connections (often 1 is optimal) than a dedicated application server.
|
||||
|
||||
@@ -31,7 +31,7 @@ When connecting to your application from serverless/edge functions, horizontally
|
||||
|
||||
They sit between the database and your client servers. They are solely optimized for sustaining high numbers of client connections and queuing and triaging queries to the database. Although they add network complexity, they are necessary when managing auto-scaling servers that can hypothetically form an infinite amount of connections.
|
||||
|
||||
### Where are the connection strings
|
||||
## Where are the connection strings
|
||||
|
||||
Supabase provides 3 database connection strings that can be used simultaneously if necessary. You can find them on the dashboard by clicking [Connect](/dashboard/project/_?showConnect=true).
|
||||
|
||||
@@ -41,7 +41,7 @@ Supabase provides 3 database connection strings that can be used simultaneously
|
||||
src="https://github.com/supabase/supabase/assets/91111415/1d653203-84d9-406a-a7c9-1f7d097f5a29"
|
||||
/>
|
||||
|
||||
#### Direct connections:
|
||||
### Direct connections:
|
||||
|
||||
> "Note uses an IPv6 address by default. [Check here to see if your network is IPv6 compatible](https://github.com/orgs/supabase/discussions/27034)"
|
||||
|
||||
@@ -50,21 +50,21 @@ Supabase provides 3 database connection strings that can be used simultaneously
|
||||
postgresql://postgres:[YOUR-PASSWORD]@db.ajrbwkcuthywfihaarmflo.supabase.co:5432/postgres
|
||||
```
|
||||
|
||||
#### Supavisor in transaction mode (port 6543)
|
||||
### Supavisor in transaction mode (port 6543)
|
||||
|
||||
```sh
|
||||
# Example transaction string
|
||||
postgresql://postgres.ajrbwkcuthywddfihrmflo:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres
|
||||
```
|
||||
|
||||
#### Supavisor in session mode (port 5432)
|
||||
### Supavisor in session mode (port 5432)
|
||||
|
||||
```sh
|
||||
# Example session string
|
||||
postgresql://postgres.ajrbwkcuthywfddihrmflo:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:5432/postgres
|
||||
```
|
||||
|
||||
### Supavisor: Transaction mode vs. Session mode?
|
||||
## Supavisor: Transaction mode vs. Session mode?
|
||||
|
||||
When a client forms a direct connection with Postgres, it usually makes a few queries but may not use the connection the entire time. In transaction mode, a client is allowed to make a single query before being sent back to the figurative "waiting room". This prevents greedy or sedentary clients from hoarding connections. In most cases, this increases query throughput and is optimal.
|
||||
|
||||
@@ -74,11 +74,11 @@ This behavior mirrors a direct connection, allowing greedy clients to monopolize
|
||||
|
||||
Depending on your application's configurations, having the pooler manage a queue of patient clients is preferable to the alternative of constantly polling the database to check for an available connection. Session mode can queue clients for up to a minute. If this isn't particularly relevant to your application design, then the primary benefit is that it is [IPv4 compatible](https://github.com/orgs/supabase/discussions/27034). Also, unlike transaction mode, it supports prepared statements.
|
||||
|
||||
### What happens when a client library, such as Prisma, connects through Supavisor?
|
||||
## What happens when a client library, such as Prisma, connects through Supavisor?
|
||||
|
||||
When clients connect to either Postgres or Supavisor, they do so with the Postgres Wire Protocol. Because of this, clients treat connections with pooler as if they were directly connected to Postgres. The pooler then smoothly acts as a messenger between the database and the client.
|
||||
|
||||
### What are "client connections"?
|
||||
## What are "client connections"?
|
||||
|
||||
In summary, they have nothing to do with front-end clients. They are the amount of backend-server connections that can connect to a serverside pooler.
|
||||
Imagine a chess tournament with 60 boards. Each board represents a connection in a database. When a player sits down at a board, it's like a client connecting to the database. They can take their time with their moves or sit there, not making any.
|
||||
@@ -87,11 +87,11 @@ But when the tournament fills up and all the boards are taken, new players are t
|
||||
|
||||
Now, imagine the tournament organizers decide to expand the venue to house 200 people without adding more tables. Even when all boards are occupied, players don't have to leave. They can wait in the wings, and the moment a board opens up, someone from the waiting area can take their place. Likewise, if someone ends their game, but wants to play again, they can go back to the waiting area. The waiting area represents the "Max Client Connections". Ultimately, the additional capacity provided by the pooler ensures fewer people are turned away from the "tournament".
|
||||
|
||||
### In the context of Supavisor, what does "pool size" mean?
|
||||
## In the context of Supavisor, what does "pool size" mean?
|
||||
|
||||
"Pool size" refers to the maximum number of direct connections the pooler can maintain per unique user, database, and mode combination. You can adjust it in the [project connect page](/dashboard/project/_/database/settings) to strike a balance between efficient resource utilization and accommodating peak traffic.
|
||||
|
||||
### What is the "user+db+mode" combination?
|
||||
## What is the "user+db+mode" combination?
|
||||
|
||||
Postgres is not a database. It is a Relational Database Management System (RDMS). Within it, you can spawn Postgres databases. In Supabase, it is a common pattern to use the default database called `postgres`, but you could create more:
|
||||
|
||||
@@ -117,7 +117,7 @@ postgres://[USER].shfmmplnqscentnakbkl:[password]@aws-0-ca-central-1.pooler.supa
|
||||
|
||||
When a distinct combination connects to your database, a new direct connection pool will be created. That means if you have two combinations connecting and the "Pool Size" is set to 120, each combination will have permission to form 120 connections. This can become problematic if collectively they exhaust all available direct connections.
|
||||
|
||||
### **Does Supavisor immediately establish the max pool size?**
|
||||
## **Does Supavisor immediately establish the max pool size?**
|
||||
|
||||
No, it doesn't. See why:
|
||||
|
||||
@@ -127,7 +127,7 @@ No, it doesn't. See why:
|
||||
- In transaction mode, once a direct connection is established, the pooler will keep it available for reuse for another client. However, if the connection remains unused for 5 minutes, the pooler will close it to free up database resources. In session mode, the connection will be immediately closed.
|
||||
- If a client is connected to the pooler, then at least 1 hot connection will be sustained, even if no client needs it.
|
||||
|
||||
### **How to change pool size**
|
||||
## **How to change pool size**
|
||||
|
||||
In the [Dashboard's Database Settings](/dashboard/project/_/database/settings), you can configure Supavisor's "Pool Size":
|
||||
|
||||
@@ -139,13 +139,13 @@ In the [Dashboard's Database Settings](/dashboard/project/_/database/settings),
|
||||
|
||||
You can also change the pool size for PostgREST's (DB API) internal pooler at the bottom of the [application settings](/dashboard/project/_/settings/api).
|
||||
|
||||
### Do all services on Supabase use Supavisor?
|
||||
## Do all services on Supabase use Supavisor?
|
||||
|
||||
Supabase Storage uses Supavisor internally. The other servers that communicate with Postgres (PostgREST, Realtime, and Auth) all rely on internal application poolers.
|
||||
|
||||
Supavisor is primarily intended for users who do not want to rely on the Supabase Client libraries and instead prefer to work with external ORMs, such as Prisma, Drizzle, and Psycopg.
|
||||
|
||||
### **Whether to change Supavisor's pool size?**
|
||||
## **Whether to change Supavisor's pool size?**
|
||||
|
||||
In an ideal scenario, Postgres would support an unlimited number of direct connections, but there's a limit to how many it can handle. If Supavisor uses most of the available connections, you risk depriving other servers, such as Auth, from accessing your database. Still, as much as possible, you want to give your pooler freedom to grow its pool as needed to service demand.
|
||||
|
||||
@@ -153,7 +153,7 @@ It's important to note that the Storage server also uses Supavisor as a unique "
|
||||
|
||||
As a rule of thumb, if you're using the DB REST API or multiple app-based "user+db+mode" combinations, try to keep the pooler's usage under 40% of available connections. Otherwise, you can cautiously increase usage to around 80%. These percentages are flexible and depend on your application's usage and setup. Monitor connection usage to determine the optimal allocation without depriving other servers of necessary connections.
|
||||
|
||||
### **How to monitor connections**
|
||||
## **How to monitor connections**
|
||||
|
||||
> EDIT: a more in-depth [troubleshooting guide](https://github.com/orgs/supabase/discussions/27141) for connection monitoring was published
|
||||
|
||||
@@ -161,7 +161,7 @@ Connection usage can be monitored with a Supabase Grafana Dashboard. It provides
|
||||
|
||||
You can check our [GitHub repo](https://github.com/supabase/supabase-grafana) for setup instructions for local deployments or free cloud deployments on [Fly.io](http://fly.io/). Refer to Supabase [documentation](/docs/guides/monitoring-and-debugging/metrics) to learn more about the metrics endpoint.
|
||||
|
||||
### **Can Supavisor really support a million connections?**
|
||||
## **Can Supavisor really support a million connections?**
|
||||
|
||||
It depends.
|
||||
|
||||
|
||||
+6
-6
@@ -6,7 +6,7 @@ keywords = []
|
||||
|
||||
When team members run SQL queries from the Dashboard SQL Editor, and if that query is logged in the Postgres Logs, it's not immediately clear who executed which query. This guide shows you how to track queries back to the specific team member who ran them.
|
||||
|
||||
### **Understanding Dashboard query execution**
|
||||
## **Understanding Dashboard query execution**
|
||||
|
||||
First, it helps to understand how Dashboard queries are executed. When someone runs a query from the SQL editor, it's routed through the `postgres` role at the database level. The Supabase Dashboard automatically appends metadata comments to queries, specifically `-- user: [UUID]`, `-- source: dashboard`, and `-- date`.
|
||||
|
||||
@@ -14,7 +14,7 @@ By default, that role has `log_statement` set to `ddl`, which means Postgres log
|
||||
|
||||
So, if someone truncates a table, and you're relying on the default logging, you won't see it.
|
||||
|
||||
### **Enabling data modification logging**
|
||||
## **Enabling data modification logging**
|
||||
|
||||
To make those operations visible, you can increase the logging level for the `postgres` role:
|
||||
|
||||
@@ -42,7 +42,7 @@ Notice that the log includes:
|
||||
|
||||
That UUID corresponds to the team member who logged in via the Supabase Dashboard and executed queries in the [SQL Editor](/dashboard/project/_/sql/new). But at this point, it's only an ID - not yet a name or email.
|
||||
|
||||
### **Mapping UUIDs to team members**
|
||||
## **Mapping UUIDs to team members**
|
||||
|
||||
To map the UUID, you'll need to query the Management API. The process looks like this:
|
||||
|
||||
@@ -72,7 +72,7 @@ The response will include entries like:
|
||||
|
||||
Now you can directly match `user_id` values from the Postgres logs to the corresponding team members.
|
||||
|
||||
### **Querying logs for specific operations**
|
||||
## **Querying logs for specific operations**
|
||||
|
||||
Navigate to the [Logs Explorer](/dashboard/project/_/logs/explorer) and query `postgres_logs`. Here's an example query that searches for data-modifying operations and maps user IDs to team members:
|
||||
|
||||
@@ -118,11 +118,11 @@ This query:
|
||||
|
||||
You can further refine your search by filtering for specific commands like `TRUNCATE` or `DELETE` where `parsed.user_name = 'postgres'`.
|
||||
|
||||
### **Tracking external tools**
|
||||
## **Tracking external tools**
|
||||
|
||||
For external tools like n8n or other applications connecting to your database, you can identify the source of database changes by appending `?application_name=example_app_name` to your connection string. This ensures the source is clearly identified in the logs, making it easier to distinguish between Dashboard operations and external tool operations.
|
||||
|
||||
### **Additional logging levels**
|
||||
## **Additional logging levels**
|
||||
|
||||
Postgres supports these `log_statement` values:
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ database_id = "c6b6ae3c-1b5b-4ba8-a40f-5f2ca1f007e2"
|
||||
|
||||
For a detailed, step-by-step guide on restoring your database from the Supabase platform to a [self-hosted Supabase](/docs/guides/self-hosting) instance, see [Restore a Platform Project to Self-Hosted](/docs/guides/self-hosting/restore-from-platform).
|
||||
|
||||
### Quick reference
|
||||
## Quick reference
|
||||
|
||||
Back up your cloud database:
|
||||
|
||||
|
||||
+13
-13
@@ -10,15 +10,15 @@ database_id = "0ce5b1e4-bd0a-439e-9fb1-8e27bad2ef10"
|
||||
sdk = [ "explain" ]
|
||||
---
|
||||
|
||||
### Introduction
|
||||
## Introduction
|
||||
|
||||
This guide is designed to help you understand how to use the Postgres [EXPLAIN and EXPLAIN ANALYZE](https://www.postgresql.org/docs/current/sql-explain.html) commands to optimize and debug SQL queries. Understanding the output of these commands can help you improve the performance of your applications by optimizing database interactions.
|
||||
|
||||
### What is explain?
|
||||
## What is explain?
|
||||
|
||||
The Postgres EXPLAIN command shows the execution plan of a SQL query. This plan describes how the Postgres database will execute the query, including how tables will be scanned—by using sequential scans, index scans, etc.—and how rows will be joined.
|
||||
|
||||
### How to use explain in Supabase
|
||||
## How to use explain in Supabase
|
||||
|
||||
**Using EXPLAIN through the SQL Editor**
|
||||
|
||||
@@ -39,7 +39,7 @@ const { data, error } = await supabase
|
||||
.explain({analyze:true,verbose:true})
|
||||
```
|
||||
|
||||
### Detailed breakdown of explain output components
|
||||
## Detailed breakdown of explain output components
|
||||
|
||||
### 1. Plan type
|
||||
|
||||
@@ -74,7 +74,7 @@ const { data, error } = await supabase
|
||||
|
||||

|
||||
|
||||
### Detailed components in explain analyze
|
||||
## Detailed components in explain analyze
|
||||
|
||||
When running EXPLAIN ANALYZE, additional information is provided, including:
|
||||
|
||||
@@ -99,7 +99,7 @@ Planning Time: 0.135 ms
|
||||
|
||||
- **Planning Time: 0.135 ms:** Planning Time refers to the amount of time the Postgres query planner takes to analyze the query and create an execution plan. This time is measured in milliseconds.
|
||||
|
||||
### You might be asking yourself now, why there is two different sets of metrics : `(cost=0.42..2.64 rows=1 width=164) (actual time=0.020..0.021 rows=1 loops=1)`?
|
||||
## You might be asking yourself now, why there is two different sets of metrics : `(cost=0.42..2.64 rows=1 width=164) (actual time=0.020..0.021 rows=1 loops=1)`?
|
||||
|
||||
To answer you, one is for the estimated cost and performance, and another for the actual performance of the query as explained above.
|
||||
|
||||
@@ -109,7 +109,7 @@ To answer you, one is for the estimated cost and performance, and another for th
|
||||
|
||||
**Identifying Bottlenecks**: If the actual time is significantly higher than expected, or if loops are more frequent than anticipated, these could be indicators of performance bottlenecks in the query.
|
||||
|
||||
### How to read a complex explain output
|
||||
## How to read a complex explain output
|
||||
|
||||
First, you have to understand that a Postgres execution plan is a tree structure consisting of several nodes. The top node (the Aggregate above) is at the top, and lower nodes are indented and start with an arrow (->). Nodes with the same indentation are on the same level (for example, the two relations combined with a join).
|
||||
|
||||
@@ -133,7 +133,7 @@ Postgres executes a plan top down, that is, it starts with producing the first r
|
||||
|
||||
On top of that, you have to multiply the cost and the time with the number of “loops” to get the total time spent in a node.
|
||||
|
||||
### Common nodes in Postgres explain output
|
||||
## Common nodes in Postgres explain output
|
||||
|
||||
| Node Type | Description |
|
||||
| --------------------- | ------------------------------------------------------------------------------ |
|
||||
@@ -155,7 +155,7 @@ On top of that, you have to multiply the cost and the time with the number of
|
||||
| **Foreign Scan** | Fetches data from foreign data sources outside the local database. |
|
||||
| **Function Scan** | Retrieves results from a set-returning function. |
|
||||
|
||||
### What to focus on in explain analyze output
|
||||
## What to focus on in explain analyze output
|
||||
|
||||
- Find the nodes where most of the execution time was spent.
|
||||
`Hash Join (cost=100.00..200.00 rows=1000 width=50) (actual time=50.012..150.023 rows=1000 loops=1)`
|
||||
@@ -176,7 +176,7 @@ Seq Scan on products (cost=0.00..100.00 rows=300 width=50) (actual time=50.000.
|
||||
Explanation:
|
||||
This sequential scan took 50 to 100 milliseconds and filtered out 2997 of 3000 rows, indicating that only a few rows met the condition. This scenario is ideal for an index on the price column to optimize the performance by reducing the need for a full table scan.
|
||||
|
||||
### Understanding the significance of milliseconds in Query Performance
|
||||
## Understanding the significance of milliseconds in Query Performance
|
||||
|
||||
Determining whether 100 milliseconds for e.g is noteworthy in the context of identifying performance bottlenecks depends on various factors:
|
||||
|
||||
@@ -190,12 +190,12 @@ For complex queries that involve multiple joins, subqueries, or aggregation func
|
||||
|
||||
So, the acceptable performance threshold can vary by application. For real-time systems or high-frequency trading platforms, even a few milliseconds can be critical, whereas for batch processing or data warehousing, longer execution times might be acceptable.
|
||||
|
||||
### Tools to interpret explain analyze output
|
||||
## Tools to interpret explain analyze output
|
||||
|
||||
Since reading a longer execution plan is quite cumbersome, you can use the website https://explain.depesz.com/ to better visualize the query. If you paste the execution plan in the text area and hit “Submit”, you will get output like this:
|
||||

|
||||
|
||||
### Tips for optimizing queries
|
||||
## Tips for optimizing queries
|
||||
|
||||
- **Add Indexes:** Improve performance by adding indexes on columns that are frequently used in WHERE clauses or JOIN conditions.
|
||||
|
||||
@@ -203,7 +203,7 @@ Since reading a longer execution plan is quite cumbersome, you can use the websi
|
||||
|
||||
- **Update Statistics:** Ensure that statistics are up to date to help the optimizer make better choices.
|
||||
|
||||
### Conclusion
|
||||
## Conclusion
|
||||
|
||||
Understanding EXPLAIN and EXPLAIN ANALYZE output can significantly enhance your ability to write efficient SQL queries. Regularly analyze query performance and make adjustments as your dataset grows and changes.
|
||||
|
||||
|
||||
+6
-6
@@ -9,7 +9,7 @@ database_id = "10186830-8cce-4f10-8cb9-7cbf39310763"
|
||||
|
||||
Since each Supabase project uses Postgres as its underlying database engine, it’s common to adjust logging settings for various reasons—whether for debugging issues, monitoring database performance, or auditing actions. However, modifying logging levels improperly can lead to an excessive amount of log data being generated, which can fill up your disk space and cause significant performance degradation or even system failure.
|
||||
|
||||
### 1. Overview of Postgres logging levels
|
||||
## 1. Overview of Postgres logging levels
|
||||
|
||||
Postgres provides multiple logging levels that allow you to control how much information gets logged. These include:
|
||||
|
||||
@@ -39,7 +39,7 @@ PANIC: database system shutdown requested
|
||||
|
||||
The default log level is set to **WARNING** through the log_min_messages setting, and we recommend keeping it that way.
|
||||
|
||||
### 2. How high log levels can affect your database
|
||||
## 2. How high log levels can affect your database
|
||||
|
||||
When users alter a high level of log settings, the database can start generating an overwhelming number of log entries. This can escalate to issues such as:
|
||||
|
||||
@@ -49,7 +49,7 @@ When users alter a high level of log settings, the database can start generating
|
||||
|
||||
- Database Lockups: In extreme cases, if the disk is filled to capacity with logs, your database could lock up, leading to downtime or severe performance degradation.
|
||||
|
||||
### 3. Common scenarios that cause log overload
|
||||
## 3. Common scenarios that cause log overload
|
||||
|
||||
Here are a few common scenarios where excessive logging can become a problem:
|
||||
|
||||
@@ -59,7 +59,7 @@ Here are a few common scenarios where excessive logging can become a problem:
|
||||
|
||||
- Frequent Write Operations: If your database processes a lot of write operations (such as inserts, updates, or deletes), even low-level logs (like NOTICE or INFO) can lead to significant log accumulation.
|
||||
|
||||
### 4. How to manage Postgres log levels effectively
|
||||
## 4. How to manage Postgres log levels effectively
|
||||
|
||||
**a. Choose the Right Log Level**
|
||||
For most users, setting Postgres logs to WARNING or ERROR is sufficient for regular operations. Here’s a general guideline:
|
||||
@@ -97,11 +97,11 @@ ALTER ROLE postgres SET log_min_messages TO 'ERROR';
|
||||
ALTER ROLE postgres RESET log_min_messages;
|
||||
```
|
||||
|
||||
### 5. Conclusion
|
||||
## 5. Conclusion
|
||||
|
||||
Postgres logs provide a powerful way to gain valuable insights into your database activity and performance when properly configured, but the key lies in finding the right balance. When set up properly, they can be incredibly useful.
|
||||
|
||||
### 6. Other resources
|
||||
## 6. Other resources
|
||||
|
||||
**a. What Events Are Logged in Postgres**
|
||||
For a detailed explanation of the types of events logged in your database (such as connection events, checkpoint events, long-running queries, cron jobs, and severity-based logging), you can refer to the official documentation here:
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ Vercel has three environments, which map to different stages of the deployment l
|
||||
- **Preview** is used for all other Git branches, including pull requests, feature branches, and persistent branches like staging. If you deploy a staging branch, it still runs under the Preview environment unless you explicitly create a separate environment in Vercel and map that branch to it.
|
||||
- **Development** is only used for local development via the Vercel CLI (`vercel dev`). It allows your local environment to pull env vars from Vercel, but it does not apply to Git branches or deployments on the platform.
|
||||
|
||||
### Creating a staging environment
|
||||
## Creating a staging environment
|
||||
|
||||
On the Hobby plan, staging is implemented by scoping Preview environment variables to a branch. On the Pro plan, staging can be configured as a dedicated environment with its own settings.
|
||||
|
||||
|
||||
+5
-5
@@ -16,11 +16,11 @@ You might be surprised to know that gaps in sequence IDs are a normal aspect of
|
||||
|
||||
It's also important to understand the distinction that sequences guarantee **uniqueness**, but not **consecutiveness**, and this should not imply any issues relating to data integrity with your database.
|
||||
|
||||
### How to check the name of your sequence
|
||||
## How to check the name of your sequence
|
||||
|
||||
If you don't know the name of your sequence, it's often formed based on a standard naming convention: table_name_id_seq, where table_name is the name of your table and id is the name of your serial column.
|
||||
|
||||
### Common reasons for gaps in sequences
|
||||
## Common reasons for gaps in sequences
|
||||
|
||||
1. Rollbacks
|
||||
One of the most common reasons for a gap is the rollback of a transaction. If you initiate a transaction that includes an insert operation, the sequence responsible for generating the ID for the new row increments. If, for any reason, the transaction doesn't complete successfully—perhaps due to a constraint violation or a deliberate decision to rollback—the insert operation is undone, but the sequence value used is not returned or reused. The documentation explains that as well:
|
||||
@@ -36,7 +36,7 @@ If you don't know the name of your sequence, it's often formed based on a standa
|
||||
4. Upserts
|
||||
When an upsert is executed, it can still increase the sequence even if it is set to do nothing on conflicts
|
||||
|
||||
### Checking for gaps
|
||||
## Checking for gaps
|
||||
|
||||
To check for gaps in the sequence of IDs in a Postgres table, you can use a SQL query that compares the sequence of IDs to a generated series of numbers that spans the same range:
|
||||
|
||||
@@ -52,7 +52,7 @@ WHERE
|
||||
|
||||
This query should help you pinpoint where gaps exist.
|
||||
|
||||
### Encountering errors and adjusting sequences
|
||||
## Encountering errors and adjusting sequences
|
||||
|
||||
In operations involving sequences, you might encounter an error message such as:
|
||||
|
||||
@@ -74,6 +74,6 @@ And reset the sequence value to match the highest ID plus one:
|
||||
Or, alternatively, adjust the sequence to a specific new value:
|
||||
`ALTER SEQUENCE '{table}_{column}_seq' RESTART WITH new_value;`
|
||||
|
||||
### Implementing a gapless ID sequence
|
||||
## Implementing a gapless ID sequence
|
||||
|
||||
If your application requires contiguous IDs and you decide to build a gapless sequence. Think twice about this, as it will serialize all transactions that use that “sequence” which will then deteriorate your data modification performance considerably. However, if your application truly requires gapless IDs, then you can use a Trigger: After a successful insert, use a database trigger to assign an ID based on a custom logic that finds the next available gapless ID.
|
||||
Reference in new issue
Block a user