diff --git a/apps/docs/app/reference/[...slug]/page.tsx b/apps/docs/app/reference/[...slug]/page.tsx
index 0ed5497704c71..560623c640846 100644
--- a/apps/docs/app/reference/[...slug]/page.tsx
+++ b/apps/docs/app/reference/[...slug]/page.tsx
@@ -46,7 +46,7 @@ export default async function ReferencePage(props: { params: Promise<{ slug: Arr
} else if (isCliReference) {
return
} else if (isApiReference) {
- return
+ return
} else if (isSelfHostingReference) {
return (
diff --git a/apps/docs/components/MetricsStackCards.data.ts b/apps/docs/components/MetricsStackCards.data.ts
index d9217a230195d..04c76f26e0267 100644
--- a/apps/docs/components/MetricsStackCards.data.ts
+++ b/apps/docs/components/MetricsStackCards.data.ts
@@ -2,7 +2,7 @@ export type MetricsStackOption = {
title: string
description: string
href: string
- iconKind: 'grafana' | 'datadog' | 'flame'
+ iconKind: 'grafana' | 'datadog' | 'elastic' | 'flame'
iconColor: string
iconBg: string
badges: { label: string; variant: 'default' | 'community' }[]
@@ -39,6 +39,16 @@ export const metricsStackOptions: MetricsStackOption[] = [
iconBg: 'rgba(99,44,166,0.1)',
badges: [{ label: 'Community', variant: 'community' }],
},
+ {
+ title: 'Elastic',
+ description:
+ "Use Elastic's managed Supabase integration to scrape metrics. The integration automatically installs dashboards, alert templates, and SLO templates as data arrives.",
+ href: 'https://www.elastic.co/docs/reference/integrations/supabase',
+ iconKind: 'elastic',
+ iconColor: '#00BFB3',
+ iconBg: 'rgba(0,191,179,0.1)',
+ badges: [{ label: 'Community', variant: 'community' }],
+ },
{
title: 'Vendor-agnostic / BYO Prometheus',
description:
diff --git a/apps/docs/components/MetricsStackCards.tsx b/apps/docs/components/MetricsStackCards.tsx
index 895a5b7daee1e..6d02659cfc307 100644
--- a/apps/docs/components/MetricsStackCards.tsx
+++ b/apps/docs/components/MetricsStackCards.tsx
@@ -1,4 +1,4 @@
-import { Datadog, Grafana } from 'icons'
+import { Datadog, Elastic, Grafana } from 'icons'
import { Flame } from 'lucide-react'
import Link from 'next/link'
import type { ReactNode } from 'react'
@@ -8,6 +8,7 @@ import { metricsStackOptions, type MetricsStackOption } from './MetricsStackCard
const ICONS: Record = {
grafana: ,
datadog: ,
+ elastic: ,
flame: ,
}
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index 8f7c97d96f7b6..08c99b5eed010 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -3047,6 +3047,10 @@ export const telemetry: NavMenuConstant = {
name: 'Datadog',
url: 'https://docs.datadoghq.com/integrations/supabase/' as `/${string}`,
},
+ {
+ name: 'Elastic',
+ url: 'https://www.elastic.co/docs/reference/integrations/supabase' as `/${string}`,
+ },
{
name: 'Vendor-agnostic setup',
url: '/guides/monitoring-and-debugging/metrics/vendor-agnostic' as `/${string}`,
@@ -3626,7 +3630,7 @@ export const references = [
label: 'Management API',
description: 'something about the reference',
icon: '/docs/img/icons/api-icon.svg',
- url: '/reference/management-api/start',
+ url: '/reference/api/introduction',
},
],
},
diff --git a/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx b/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx
index 98014a389669a..addbd36aba80a 100644
--- a/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx
+++ b/apps/docs/content/guides/monitoring-and-debugging/metrics.mdx
@@ -39,5 +39,6 @@ Pick the workflow that best matches your tooling. Cards link to Supabase-authore
- [Supabase Grafana repository](https://github.com/supabase/supabase-grafana) for dashboard JSON and alert examples.
- [Grafana Cloud’s Supabase integration doc](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-supabase/) (community-maintained, built on this Metrics API).
- [Datadog’s Supabase integration doc](https://docs.datadoghq.com/integrations/supabase/) (community-maintained, built on this Metrics API).
+- [Elastic’s Supabase integration doc](https://www.elastic.co/docs/reference/integrations/supabase) (community-maintained).
- [Log Drains ](/docs/guides/monitoring-and-debugging/log-drains) for exporting event-based telemetry alongside metrics.
- [Query Performance report](/dashboard/project/_/observability/query-performance) for built-in visualizations based on the same underlying metrics.
diff --git a/apps/docs/content/guides/platform/privatelink.mdx b/apps/docs/content/guides/platform/privatelink.mdx
index 2ccb08fc65f4e..a934dc535bd23 100644
--- a/apps/docs/content/guides/platform/privatelink.mdx
+++ b/apps/docs/content/guides/platform/privatelink.mdx
@@ -6,7 +6,7 @@ description: 'Secure private network connectivity to your Supabase database usin
-PrivateLink is currently in beta and available only to Team and Enterprise customers.
+PrivateLink is available only to Team and Enterprise customers.
Contact support if you would like to create a PrivateLink connection for a read-only replica.
@@ -20,13 +20,12 @@ By enabling PrivateLink, database connections never traverse the public internet
Supabase PrivateLink is an organisation level configuration. It works by sharing a [VPC Lattice Resource Configuration](https://docs.aws.amazon.com/vpc-lattice/latest/ug/resource-configuration.html) to any number of AWS Accounts for each of your Supabase projects. Connectivity can be achieved by either associating the Resource Configuration to a PrivateLink endpoint, or a [VPC Lattice Service Network](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html). This means:
- Database traffic flows through private AWS infrastructure only
-- Connection latency is typically reduced compared to public internet routing
- Network isolation provides enhanced security posture
- Attack surface is minimized by eliminating public exposure
The connection architecture changes from public internet routing to a dedicated private path through AWS's secure network backbone.
-Supabase PrivateLink currently supports direct database and PgBouncer connections only. It does not support other Supabase services like API, Storage, Auth, or Realtime. These services will continue to operate over public internet connections.
+Supabase PrivateLink supports direct database connections on port `5432` and PgBouncer connections on port `6543`. It does not support other Supabase services like API, Storage, Auth, or Realtime. These services will continue to operate over public internet connections.
## Requirements
@@ -76,9 +75,11 @@ Ensure your security groups allow traffic on the appropriate ports:
1. Navigate to the [VPC console > Security Groups](https://console.aws.amazon.com/vpcconsole/home#SecurityGroups:)
2. Create a new security group for the endpoint or service network by clicking [Create security group](https://console.aws.amazon.com/vpcconsole/home#CreateSecurityGroup:)
3. Give your security group a descriptive name and select the appropriate VPC
-4. Add an inbound rule for:
- - Type: Postgres (TCP, port 5432)
- - Destination that is appropriate for your network. i.e. the subnet of your VPC or security group of your application instances
+4. Add inbound rule(s) for the connection mode you use:
+ - Direct connection: Postgres (TCP, port `5432`)
+ - PgBouncer connection: Custom TCP (port `6543`)
+ - If you use both direct and PgBouncer connections, add both rules
+ - Set the destination appropriate for your network (for example, your VPC subnet or your application instances' security group)
5. Finish creating the security group by clicking **Create security group**
### Step 4: Create connection
@@ -127,7 +128,11 @@ Verify the private connection is working correctly from your VPC:
3. Test the connection using the private endpoint:
```bash
+# Direct connection (Postgres)
psql "postgresql://[username]:[password]@[private-endpoint]:5432/postgres"
+
+# PgBouncer connection
+psql "postgresql://[username]:[password]@[private-endpoint]:6543/postgres"
```
You should see a successful connection without any public internet traffic.
@@ -141,27 +146,33 @@ Configure your applications to use the private connection details:
3. Update any database connection pooling configurations
4. Test application connectivity thoroughly
-Example connection string update:
+Example connection string updates:
```
+# Direct connection (Postgres)
# Before (public)
postgresql://user:pass@db.[project-ref].supabase.co:5432/postgres
# After (private)
postgresql://user:pass@your-private-endpoint.vpce.amazonaws.com:5432/postgres
-```
-### Step 7: Disable public connectivity (optional)
+# PgBouncer connection
+# Before (public)
+postgresql://user:pass@db.[project-ref].supabase.co:6543/postgres
+
+# After (private)
+postgresql://user:pass@your-private-endpoint.vpce.amazonaws.com:6543/postgres
+```
-For maximum security, you can disable public internet access for your database:
+### Step 7: Restrict public database access (optional)
-1. Contact Supabase support to disable public connectivity
-2. Ensure all applications are successfully using the private connection
-3. Update any monitoring or backup tools to use the private endpoint
+For maximum security, you can restrict public database access in your project settings:
-## Beta limitations
+1. Go to [**Database** > **Settings**](/dashboard/project/_/database/settings)
+2. In **Network Restrictions**, enable **Restrict all access**
+3. Ensure all applications, monitoring, and backup tools are using the private endpoint before enabling this setting
-During the beta phase:
+## Limitations
- **Read Replicas**: To establish PrivateLink with a Read Replica, reach out to your account rep.
- **Feature Evolution**: The setup process and capabilities may evolve as we refine the offering
diff --git a/apps/docs/content/guides/security/platform-security.mdx b/apps/docs/content/guides/security/platform-security.mdx
index 43003089c3b1d..e6ed64b34c023 100644
--- a/apps/docs/content/guides/security/platform-security.mdx
+++ b/apps/docs/content/guides/security/platform-security.mdx
@@ -61,6 +61,6 @@ For configuration information, see [PrivateLink](/docs/guides/platform/privateli
-PrivateLink is currently in beta. To establish PrivateLink with a Read Replica, reach out to your account rep.
+To establish PrivateLink with a Read Replica, reach out to your account rep.
diff --git a/apps/docs/content/troubleshooting/schema-pg_pgrst_no_exposed_schemas-does-not-exist.mdx b/apps/docs/content/troubleshooting/schema-pg_pgrst_no_exposed_schemas-does-not-exist.mdx
index 41e41acd67ebb..3124757bbf0f2 100644
--- a/apps/docs/content/troubleshooting/schema-pg_pgrst_no_exposed_schemas-does-not-exist.mdx
+++ b/apps/docs/content/troubleshooting/schema-pg_pgrst_no_exposed_schemas-does-not-exist.mdx
@@ -19,3 +19,38 @@ PostgREST logs showing the error:
- Currently, we don't really shutdown PostgREST when the Data API is disabled. You will see a schema called `pg_pgrst_no_exposed_schemas` added in the exposed schemas.
- This should not adversely affect the project, although it may result in additional entries in your logs.
- We're aware of this issue and are working on it.
+
+## Workaround
+
+To stop the missing-schema log entries:
+
+1. Open the SQL Editor.
+2. Run the following statements:
+
+ ```sql
+ -- Create a schema with nothing inside
+ create schema pgrst_no_exposed_schemas;
+
+ -- Set the db-schemas configuration
+ alter role authenticator set pgrst.db_schemas = 'pgrst_no_exposed_schemas';
+
+ -- Reload PostgREST's schema cache and configuration
+ notify pgrst;
+ ```
+
+PostgREST now exposes an empty schema, which stops the missing-schema errors.
+
+## Re-enable the Data API
+
+Before you re-enable the data API:
+
+1. Open the SQL Editor.
+2. Run the following statements:
+
+ ```sql
+ -- Reset the db-schemas configuration
+ alter role authenticator reset pgrst.db_schemas;
+
+ -- Reload PostgREST's schema cache and configuration
+ notify pgrst;
+ ```
diff --git a/apps/docs/features/docs/Reference.apiPage.tsx b/apps/docs/features/docs/Reference.apiPage.tsx
index 3e77558f3e6a0..e8344cb3a8560 100644
--- a/apps/docs/features/docs/Reference.apiPage.tsx
+++ b/apps/docs/features/docs/Reference.apiPage.tsx
@@ -1,13 +1,32 @@
+import { notFound, redirect } from 'next/navigation'
+
import { MenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu'
import { reference_api } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
-import { ClientLibIntroduction } from '~/features/docs/Reference.introduction'
+import { getSectionsBySlug } from '~/features/docs/Reference.generated.singleton'
import { ReferenceNavigation } from '~/features/docs/Reference.navigation'
import { ReferenceContentScrollHandler } from '~/features/docs/Reference.navigation.client'
-import { RefSections } from '~/features/docs/Reference.sections'
+import { SectionSwitch } from '~/features/docs/Reference.sections'
import { LayoutMainContent } from '~/layouts/DefaultLayout'
import { SidebarSkeleton } from '~/layouts/MainSkeleton'
-export async function ApiReferencePage() {
+export async function ApiReferencePage({ path }: { path: Array }) {
+ const operationSlug = path[0]
+
+ if (!operationSlug) {
+ redirect('/reference/api/introduction')
+ }
+
+ return
+}
+
+// DOCS-1268: one endpoint per page, reusing the same SectionSwitch (and
+// therefore the same ApiEndpointSection/MarkdownSection) that used to render
+// every operation on the single monolithic /reference/api page.
+async function ApiOperationPage({ operationSlug }: { operationSlug: string }) {
+ const sectionsBySlug = await getSectionsBySlug('api', 'latest')
+ const section = sectionsBySlug?.get(operationSlug)
+ if (!section) notFound()
+
return (
}
>
-
-
+
diff --git a/apps/docs/features/docs/Reference.navigation.client.tsx b/apps/docs/features/docs/Reference.navigation.client.tsx
index 4ddf294fd202b..b676573baaf06 100644
--- a/apps/docs/features/docs/Reference.navigation.client.tsx
+++ b/apps/docs/features/docs/Reference.navigation.client.tsx
@@ -239,11 +239,16 @@ export function RefLink({
section,
skipChildren = false,
className,
+ realNavigation,
}: {
basePath: string
section: AbbrevApiReferenceSection
skipChildren?: boolean
className?: string
+ // Spike (DOCS-1268): when true, this link does a real navigation instead of
+ // the scroll-hijack below — used only by the API reference, whose endpoints
+ // are now real pages. Undefined everywhere else preserves current behavior.
+ realNavigation?: boolean
}) {
const ref = useRef(null)
@@ -260,8 +265,11 @@ export function RefLink({
}, [isActive, className])
const onClick = useCallback(
- (evt: MouseEvent) => createReferenceSubsectionNavigator(href, section.slug)(evt),
- [href, section.slug]
+ (evt: MouseEvent) => {
+ if (realNavigation) return
+ createReferenceSubsectionNavigator(href, section.slug)(evt)
+ },
+ [href, section.slug, realNavigation]
)
if (!('title' in section)) return null
@@ -272,13 +280,13 @@ export function RefLink({
return (
<>
{isCompoundSection ? (
-
+
) : (
{
return (
-
+
)
})}
diff --git a/apps/docs/features/docs/Reference.navigation.tsx b/apps/docs/features/docs/Reference.navigation.tsx
index 51e594b2874c2..393624245c307 100644
--- a/apps/docs/features/docs/Reference.navigation.tsx
+++ b/apps/docs/features/docs/Reference.navigation.tsx
@@ -19,6 +19,10 @@ interface ReferenceNavigationProps {
libPath: string
version: string
isLatestVersion: boolean
+ // Spike (DOCS-1268): API reference sidebar links navigate to real pages
+ // instead of scrolling within one giant page. SDK/CLI/self-hosting callers
+ // never pass this, so their behavior is unchanged.
+ realNavigation?: boolean
}
export async function ReferenceNavigation({
@@ -28,6 +32,7 @@ export async function ReferenceNavigation({
libPath,
version,
isLatestVersion,
+ realNavigation,
}: ReferenceNavigationProps) {
const navSections = await getReferenceSections(libraryId, version)
const filteredNavSections = navSections?.filter((section) => section.title !== 'Auth')
@@ -46,11 +51,11 @@ export async function ReferenceNavigation({
{displayedNavSections?.map((section, index) =>
section.type === 'category' ? (