From 6fcb98d927f5a7bbb409fba2e67d832daa4d3157 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Thu, 22 May 2025 14:07:06 -0400 Subject: [PATCH] docs(pg17): add docs on pg17 upgrades (#35431) --- .../docs/components/Extensions/Extensions.tsx | 7 ++- apps/docs/content/guides/auth/auth-hooks.mdx | 2 - .../auth-hooks/custom-access-token-hook.mdx | 52 ----------------- .../guides/database/extensions/plv8.mdx | 6 ++ .../database/extensions/timescaledb.mdx | 6 ++ .../content/guides/database/functions.mdx | 2 +- ...ims-and-role-based-access-control-rbac.mdx | 58 ------------------- .../content/guides/platform/upgrading.mdx | 35 +++++++---- apps/www/data/features.tsx | 1 - packages/shared-data/extensions.json | 12 ++-- 10 files changed, 52 insertions(+), 129 deletions(-) diff --git a/apps/docs/components/Extensions/Extensions.tsx b/apps/docs/components/Extensions/Extensions.tsx index daf214a7db..b2228bb9d7 100644 --- a/apps/docs/components/Extensions/Extensions.tsx +++ b/apps/docs/components/Extensions/Extensions.tsx @@ -2,7 +2,7 @@ import { X } from 'lucide-react' import Link from 'next/link' import React, { useState } from 'react' import { extensions } from 'shared-data' -import { Input } from 'ui' +import { Badge, Input } from 'ui' import { GlassPanel } from 'ui-patterns/GlassPanel' type Extension = { @@ -116,6 +116,11 @@ export default function Extensions() {

{extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)}

+ {extension.deprecated && ( + + Deprecated in {extension.deprecated.join(', ')} + + )} ))} diff --git a/apps/docs/content/guides/auth/auth-hooks.mdx b/apps/docs/content/guides/auth/auth-hooks.mdx index 4f0f198579..2bf8d105f6 100644 --- a/apps/docs/content/guides/auth/auth-hooks.mdx +++ b/apps/docs/content/guides/auth/auth-hooks.mdx @@ -197,8 +197,6 @@ We recommend that you do not use any tag and explicitly grant permissions to `su Read more about `security definer` tag [in our database guide](/docs/guides/database/functions#security-definer-vs-invoker). -There are no restrictions as to what language can be used to write a Postgres Hook. If [PL/pgSQL](https://www.postgresql.org/docs/current/plpgsql.html) is too difficult consider using the [plv8](/docs/guides/database/extensions/plv8) extension which lets you use JavaScript to define functions. - Once done, save your Auth Hook as a migration in order to version the Auth Hook and share it with other team members. Run [`supabase migration new`](/docs/reference/cli/supabase-migration-new) to create a migration. diff --git a/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx b/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx index aff8766f93..d26c8eee48 100644 --- a/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx +++ b/apps/docs/content/guides/auth/auth-hooks/custom-access-token-hook.mdx @@ -314,58 +314,6 @@ revoke all from authenticated, anon, public; ``` - - -You can add custom claims to the access token. In this example, we fetch the level of an existing user from the `profiles` table and assign new users a default level of zero. - -For convenience, we enable the `plv8` extension under [`Database > Extensions`](/dashboard/project/_/database/extensions) to run JavaScript within our query. - -Create a `profiles` table to hold information: - -```sql -create table profiles ( - user_id uuid not null primary key references auth.users (id), - level integer, - is_admin boolean not null default false -); -``` - -```sql -create or replace function custom_access_token_hook(event jsonb) -returns jsonb -language plv8 -as $$ - var user_level; - - -- Fetch the current user's level from the profiles table - var result = plv8.execute("select level from public.profiles where user_id = $1", [event.user_id]); - if (result.length > 0) { - user_level = result[0].level; - } else { - -- Assign a default level of 0 if no level is found - user_level = 0; - } - - -- Check if 'claims' exists in the event object; if not, initialize it - if (!event.claims) { - event.claims = {}; - } - - -- Update the level in the claims - event.claims.level = user_level; - - return event; -$$; - -grant all - on table public.profiles - to supabase_auth_admin; - -revoke all - on table public.profiles - from authenticated, anon, public; -``` - You can restrict access to internal applications with a hook. For example, you can require that employees log in via [SAML Single Sign On (SSO)](/docs/guides/auth/sso/auth-sso-saml). You can exempt select employees from the policy via an allowlist. diff --git a/apps/docs/content/guides/database/extensions/plv8.mdx b/apps/docs/content/guides/database/extensions/plv8.mdx index 240856485d..eb49765550 100644 --- a/apps/docs/content/guides/database/extensions/plv8.mdx +++ b/apps/docs/content/guides/database/extensions/plv8.mdx @@ -4,6 +4,12 @@ title: 'plv8: JavaScript Language' description: 'JavaScript language for PostgreSQL.' --- + + +The `plv8` extension is deprecated in projects using Postgres 17. It continues to be supported in projects using Postgres 15, but will need to dropped before those projects are upgraded to Postgres 17. See the [Upgrading to Postgres 17 notes](/docs/guides/platform/upgrading#upgrading-to-postgres-17) for more information. + + + The `plv8` extension allows you use JavaScript within Postgres. ## Overview diff --git a/apps/docs/content/guides/database/extensions/timescaledb.mdx b/apps/docs/content/guides/database/extensions/timescaledb.mdx index fa75a8d0c6..5d4120418a 100644 --- a/apps/docs/content/guides/database/extensions/timescaledb.mdx +++ b/apps/docs/content/guides/database/extensions/timescaledb.mdx @@ -4,6 +4,12 @@ title: 'timescaledb: Time-Series data' description: 'Scalable time-series data storage and analysis' --- + + +The `timescaledb` extension is deprecated in projects using Postgres 17. It continues to be supported in projects using Postgres 15, but will need to dropped before those projects are upgraded to Postgres 17. See the [Upgrading to Postgres 17 notes](/guides/platform/upgrading#upgrading-to-postgres-17) for more information. + + + [`timescaledb`](https://docs.timescale.com/timescaledb/latest/) is a Postgres extension designed for improved handling of time-series data. It provides a scalable, high-performance solution for storing and querying time-series data on top of a standard Postgres database. `timescaledb` uses a time-series-aware storage model and indexing techniques to improve performance of Postgres in working with time-series data. The extension divides data into chunks based on time intervals, allowing it to scale efficiently, especially for large data sets. The data is then compressed, optimized for write-heavy workloads, and partitioned for parallel processing. `timescaledb` also includes a set of functions, operators, and indexes that work with time-series data to reduce query times, and make data easier to work with. diff --git a/apps/docs/content/guides/database/functions.mdx b/apps/docs/content/guides/database/functions.mdx index 35ac1c32b4..c39a94aad7 100644 --- a/apps/docs/content/guides/database/functions.mdx +++ b/apps/docs/content/guides/database/functions.mdx @@ -51,7 +51,7 @@ At it's most basic a function has the following parts: 1. `create or replace function hello_world()`: The function declaration, where `hello_world` is the name of the function. You can use either `create` when creating a new function or `replace` when replacing an existing function. Or you can use `create or replace` together to handle either. 2. `returns text`: The type of data that the function returns. If it returns nothing, you can `returns void`. -3. `language sql`: The language used inside the function body. This can also be a procedural language: `plpgsql`, `plv8`, `plpython`, etc. +3. `language sql`: The language used inside the function body. This can also be a procedural language: `plpgsql`, `plpython`, etc. 4. `as $$`: The function wrapper. Anything enclosed inside the `$$` symbols will be part of the function body. 5. `select 'hello world';`: A simple function body. The final `select` statement inside a function body will be returned if there are no statements following it. 6. `$$;`: The closing symbols of the function wrapper. diff --git a/apps/docs/content/guides/database/postgres/custom-claims-and-role-based-access-control-rbac.mdx b/apps/docs/content/guides/database/postgres/custom-claims-and-role-based-access-control-rbac.mdx index 111da7db72..d1e8114ca5 100644 --- a/apps/docs/content/guides/database/postgres/custom-claims-and-role-based-access-control-rbac.mdx +++ b/apps/docs/content/guides/database/postgres/custom-claims-and-role-based-access-control-rbac.mdx @@ -137,64 +137,6 @@ to supabase_auth_admin using (true) ``` - - - -```sql supabase/migrations/auth_hook.sql --- Enable the "plv8" extension -create extension plv8; - --- Create the auth hook function -create or replace function custom_access_token_hook(event jsonb) -returns jsonb -language plv8 -as $$ - var user_role; - - // Fetch the current user's user_role from the public user_roles table. - var result = plv8.execute("select role from public.user_roles where user_id = $1", [event.user_id]); - if (result.length > 0) { - user_role = result[0].role; - } else { - // Assign null - user_role = null; - } - - // Check if 'claims' exists in the event object; if not, initialize it - if (!event.claims) { - event.claims = {}; - } - - // Update the level in the claims - event.claims.user_role = user_role; - - return event; -$$; - -grant usage on schema public to supabase_auth_admin; - -grant execute - on function public.custom_access_token_hook - to supabase_auth_admin; - -revoke execute - on function public.custom_access_token_hook - from authenticated, anon, public; - -grant all - on table public.user_roles -to supabase_auth_admin; - -revoke all - on table public.user_roles - from authenticated, anon, public; - -create policy "Allow auth admin to read user roles" ON public.user_roles -as permissive for select -to supabase_auth_admin -using (true) -``` - diff --git a/apps/docs/content/guides/platform/upgrading.mdx b/apps/docs/content/guides/platform/upgrading.mdx index 6ab96ea03b..2f70f5cdb9 100644 --- a/apps/docs/content/guides/platform/upgrading.mdx +++ b/apps/docs/content/guides/platform/upgrading.mdx @@ -51,15 +51,15 @@ When you pause and restore a project, the restored database includes the latest Note that a pause + restore upgrade involves tearing down your project's resources before bringing them back up again. If the restore process should fail, manual intervention from Supabase support will be required to bring your project back online. -### Caveats +## Caveats Regardless of the upgrade method, a few caveats apply: -#### Logical replication +### Logical replication If you are using logical replication, the replication slots will not be preserved by the upgrade process. You will need to manually recreate them after the upgrade with the method `pg_create_logical_replication_slot`. Refer to the Postgres docs on [Replication Management Functions](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-REPLICATION) for more details about the method. -#### Breaking changes +### Breaking changes Newer versions of services can break functionality or change the performance characteristics you rely on. If your project is eligible for an upgrade, you will be able to find your current service versions from within [the Supabase dashboard](https://supabase.com/dashboard/project/_/settings/infrastructure). @@ -70,7 +70,7 @@ Breaking changes are generally only present in major version upgrades of Postgre If you are upgrading from a significantly older version, you will need to consider the release notes for any intermediary releases as well. -#### Time limits +### Time limits Starting from 2024-06-24, when a project is paused, users then have a 90-day window to restore the project on the platform from within Supabase Studio. @@ -100,22 +100,22 @@ If you upgrade to a paid plan while your project is paused, any expired one-clic src="/docs/img/guides/platform/paused-paid-tier.png" /> -#### Disk sizing +### Disk sizing When upgrading, the Supabase platform will "right-size" your disk based on the current size of the database. For example, if your database is 100GB in size, and you have a 200GB disk, the upgrade will reduce the disk size to 120GB (1.2x the size of your database). -#### Objects dependent on Postgres extensions +### Objects dependent on Postgres extensions In-place upgrades do not support upgrading of databases containing reg\* data types referencing system OIDs. If you have created any objects that depend on the following extensions, you will need to recreate them after the upgrade. -#### `pg_cron` records +### `pg_cron` records [pg_cron](https://github.com/citusdata/pg_cron#viewing-job-run-details) does not automatically clean up historical records. This can lead to extremely large `cron.job_run_details` tables if the records are not regularly pruned; you should clean unnecessary records from this table prior to an upgrade. During an in-place upgrade, the `pg_cron` extension gets dropped and recreated. Prior to this process, the `cron.job_run_details` table is duplicated to avoid losing historical logs. The instantaneous disk pressure created by duplicating an extremely large details table can cause at best unnecessary performance degradation, or at worst, upgrade process failures. -#### Extensions +### Extensions In-place upgrades do not currently support upgrading of databases using extensions older than the following versions: @@ -145,10 +145,25 @@ WHERE rolcanlogin = true ALTER ROLE WITH PASSWORD ''; ``` -#### Database size reduction +### Database size reduction As part of the upgrade process, maintenance operations such as [vacuuming](https://www.postgresql.org/docs/current/routine-vacuuming.html#ROUTINE-VACUUMING) are also executed. This can result in a reduction in the reported database size. -#### Post-upgrade validation +### Post-upgrade validation Supabase performs extensive pre- and post-upgrade validations to ensure that the database has been correctly upgraded. However, you should plan for your own application-level validations, as there might be changes you might not have anticipated, and this should be budgeted for when planning your downtime window. + +## Specific upgrade notes + +### Upgrading to Postgres 17 + +In projects using Postgres 17, the following extensions are deprecated: + +- `plcoffee` +- `plls` +- `plv8` +- `timescaledb` + +Existing projects on lower versions of Postgres are not impacted, and the extensions will continue to be supported on projects using Postgres 15, until the end of life of Postgres 15 on the Supabase platform. + +Projects planning to upgrade from Postgres 15 to Postgres 17 need to drop the extensions by [disabling them in the Supabase Dashboard](/dashboard/project/_/database/extensions). diff --git a/apps/www/data/features.tsx b/apps/www/data/features.tsx index a75f004ddb..b1f440c8c4 100644 --- a/apps/www/data/features.tsx +++ b/apps/www/data/features.tsx @@ -514,7 +514,6 @@ Popular Postgres extensions supported by Supabase include: - pgjwt: Allows for JSON Web Token (JWT) generation and verification - pg_net: Enables making HTTP requests from the database - pgroonga: Provides full-text search capabilities for various languages -- timescaledb: Optimizes the database for time-series data Postgres extensions are valuable for a wide range of applications, from GIS and machine learning projects to security-focused applications and IoT systems dealing with time-series data. diff --git a/packages/shared-data/extensions.json b/packages/shared-data/extensions.json index 24fd7000e9..6b6e689e5a 100644 --- a/packages/shared-data/extensions.json +++ b/packages/shared-data/extensions.json @@ -419,7 +419,8 @@ "link": "https://github.com/plv8/plv8/blob/master/doc/plv8.md#coffeescript-extension", "github_url": null, "product": null, - "product_url": null + "product_url": null, + "deprecated": ["Postgres 17"] }, { "name": "pljava", @@ -436,7 +437,8 @@ "link": "https://github.com/plv8/plv8/blob/master/doc/plv8.md#livescript-extension", "github_url": null, "product": null, - "product_url": null + "product_url": null, + "deprecated": ["Postgres 17"] }, { "name": "plpgsql", @@ -463,7 +465,8 @@ "link": "/guides/database/extensions/plv8", "github_url": null, "product": null, - "product_url": null + "product_url": null, + "deprecated": ["Postgres 17"] }, { "name": "postgis", @@ -544,7 +547,8 @@ "link": "/guides/database/extensions/timescaledb", "github_url": null, "product": null, - "product_url": null + "product_url": null, + "deprecated": ["Postgres 17"] }, { "name": "tsm_system_rows",