mirror of
https://github.com/supabase/supabase.git
synced 2026-10-19 16:19:10 +03:00
clarifications
This commit is contained in:
1 parent
27c8f9bfae
commit
0b39f0efce
1 file changed
+28
-43
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 'PostgREST v11: configurable role settings, isolation level and more'
|
||||
description: 'PostgREST v11 new features'
|
||||
title: 'What''s new in PostgREST v11.1'
|
||||
description: 'PostgREST v11.1 new features'
|
||||
author: steve_chavez
|
||||
image: lw6-community/postgrest.png
|
||||
thumb: lw6-community/postgrest.png
|
||||
@@ -10,31 +10,32 @@ tags:
|
||||
- isolation level
|
||||
- transactions
|
||||
- roles
|
||||
- planetpg
|
||||
date: '2023-05-03'
|
||||
toc_depth: 3
|
||||
---
|
||||
|
||||
PostgREST 11 is now fully released! In addition to the [pre-release](https://supabase.com/blog/postgrest-11-prerelease) features, we’ve added security, configuration, and querying improvements. Here is what's new:
|
||||
PostgREST 11.1 is now available on the Supabase platform. Besides the [pre-release](https://supabase.com/blog/postgrest-11-prerelease) features, we’ve added configuration and querying improvements. Here is what's new:
|
||||
|
||||
## Configurable Role Settings
|
||||
## Impersonated Role Settings
|
||||
|
||||
Role settings are now applied on every request, you can set these with a regular `ALTER ROLE <role> SET <setting>`. This is useful, for example, to prevent web users from running expensive queries.
|
||||
Every role that passes [PostgREST JWT Authentication](https://postgrest.org/en/stable/references/auth.html#jwt-based-user-impersonation) is an impersonated role. On the Supabase platform, these are the ``anon``, ``authenticated`` and ``service_role`` roles. Plus any role you create which is member of ``authenticator`` (the role PostgREST logins with).
|
||||
|
||||
These roles can now have settings applied to their HTTP requests. You can set these with a regular `ALTER ROLE <role> SET <setting>`. This is useful, for example, to prevent web users from running expensive queries.
|
||||
|
||||
Let’s try it by setting a statement timeout and cost limit.
|
||||
|
||||
### Statement timeout
|
||||
|
||||
`statement_timeout` aborts any statement that takes more than the specified amount of time. Let’s set it for the usual `anon`, `authenticated` and `service_role` roles:
|
||||
`statement_timeout` aborts any statement that takes more than the specified amount of time. Let’s set it for the `anon`, `authenticated` and `service_role` roles:
|
||||
|
||||
```sql
|
||||
-- anonymous users can only run queries that take 100 milliseconds max
|
||||
-- anonymous users can run queries that take 100 milliseconds max
|
||||
alter role anon set statement_timeout = '100ms';
|
||||
|
||||
-- authenticated users can only run queries that take 5 seconds max
|
||||
-- authenticated users can run queries that take 5 seconds max
|
||||
alter role authenticated set statement_timeout = '5s';
|
||||
|
||||
-- backend-only users can only run queries that take 15 seconds max
|
||||
-- backend-only users can run queries that take 15 seconds max
|
||||
alter role service_role set statement_timeout = '15s';
|
||||
```
|
||||
|
||||
@@ -44,7 +45,7 @@ You need to reload PostgREST config cache to apply these changes.
|
||||
NOTIFY pgrst, 'reload config';
|
||||
```
|
||||
|
||||
Now, suppose you do an expensive query, by having a big table and a filter on an unindexed column(this will cause a full table scan):
|
||||
Now, suppose you do an expensive query. Having a big table and a filter on an unindexed column (this will cause a full table scan):
|
||||
|
||||
```jsx
|
||||
const { data, error } = await supabase
|
||||
@@ -64,9 +65,15 @@ Then, after 5 seconds, the request will be aborted and the response will be:
|
||||
}
|
||||
```
|
||||
|
||||
### Statement cost limit
|
||||
Note that there's already a global ``statement_timeout`` set but you can be more fine-grained with this. See https://supabase.com/docs/guides/database/timeouts for more details.
|
||||
|
||||
With `statement_timeout`, queries will still run for that length of time, consuming resources until they’re terminated. To prevent this, you can abort queries based on their plan cost — this is determined at the planning phase, before they get executed.
|
||||
### Statement Cost Limit
|
||||
|
||||
With a statement timeout, expensive queries will still run for a length of time. Consuming resources until they’re terminated.
|
||||
|
||||
The [pg_plan_filter](https://github.com/pgexperts/pg_plan_filter) extension (available on the Supabase platform), brings a statement cost limit. This abort queries at the planning phase, before they get executed.
|
||||
|
||||
You can use it like:
|
||||
|
||||
```sql
|
||||
-- anonymous users can only run cheap queries
|
||||
@@ -101,21 +108,15 @@ Then, immediately, the request will be aborted and the response will be:
|
||||
}
|
||||
```
|
||||
|
||||
This uses the [pg_plan_filter](https://github.com/pgexperts/pg_plan_filter) extension(available on the Supabase platform) and requires tuning to get the cost limit right. You should use this with care as it can invalidate legitimate queries.
|
||||
Tuning is required to get the cost limit right. You should use the `plan_filter.statement_cost_limit` with care as it can invalidate legitimate queries.
|
||||
|
||||
## Configurable transaction isolation level
|
||||
## Configurable Transaction Isolation Level
|
||||
|
||||
By default, all queries in PostgREST run in a transaction with the default *Read Committed* isolation level.
|
||||
By default, all queries run in a transaction with the default *read committed* isolation level.
|
||||
|
||||
```sql
|
||||
BEGIN ISOLATION LEVEL READ COMMITTED;
|
||||
-- <your_query>
|
||||
COMMIT;
|
||||
```
|
||||
You can now modify this with the `default_transaction_isolation` setting.
|
||||
|
||||
Now you can change this by settting `default_transaction_isolation`.
|
||||
|
||||
You can do it per-function:
|
||||
If you want a function to run with *repeatable read* isolation level:
|
||||
|
||||
```sql
|
||||
create function hello()
|
||||
@@ -125,29 +126,15 @@ $$ language sql
|
||||
set default_transaction_isolation = 'repeatable read';
|
||||
```
|
||||
|
||||
Or per-role, which will affect all queries ran by that role:
|
||||
Or if you want a role to run its queries with a *serializable* isolation level:
|
||||
|
||||
```sql
|
||||
alter role service_role set default_transaction_isolation = 'serializable';
|
||||
|
||||
NOTIFY pgrst, 'reload config'; -- reload postgREST config cache
|
||||
```
|
||||
|
||||
Trying out the function above.
|
||||
|
||||
```jsx
|
||||
const { data, error } = await supabase
|
||||
.rpc('hello')
|
||||
```
|
||||
|
||||
Will result in PostgREST running the query with the *Repeatable Read* isolation level:
|
||||
|
||||
```sql
|
||||
BEGIN ISOLATION LEVEL REPEATABLE READ;
|
||||
-- SELECT hello();
|
||||
COMMIT;
|
||||
```
|
||||
|
||||
Note that the default *Read Committed* is good enough for almost all use cases. Using higher isolation levels will incur in overhead as they use more sophisticated locking.
|
||||
Note that the default *read committed* is good enough for almost all use cases. Higher isolation levels incur in overhead as they use more sophisticated locking. They're only needed in special cases.
|
||||
|
||||
## Bulk insert JSON with default values
|
||||
|
||||
@@ -220,8 +207,6 @@ For completeness, the `all` modifier is also included.
|
||||
|
||||
There you have it, now you can make your API more secure with role settings and use higher isolation levels without resorting to direct PostgreSQL connections.
|
||||
|
||||
PostgREST v11 is being rolled on the Supabase platform, it will be available for new projects on the coming week.
|
||||
|
||||
## More Postgres resources
|
||||
|
||||
- [Storing OpenAI embeddings in Postgres with pgvector](https://supabase.com/blog/openai-embeddings-postgres-vector)
|
||||
|
||||
Reference in new issue
Block a user