One Server

Docs

Queues · Vault · GraphQL · network restrictions

Queues like pgmq, encrypted secrets inside the database (Vault), /graphql/v1, and address limits and TLS for direct connections.

Queues, Vault, GraphQL, network restrictions

All of these are for a project in a database of its own (p_<ref>). New projects have one from the start.

Queues (pgmq)

The same SQL functions as pgmq. The first create_queue installs the pgmq schema.

select pgmq.create('jobs');
select * from pgmq.send('jobs', '{"to": "[email protected]"}');
select * from pgmq.read('jobs', 30, 10);
select pgmq.archive('jobs', 1);
select pgmq.delete('jobs', 2);
select * from pgmq.pop('jobs');
select * from pgmq.metrics('jobs');

Tools: list_queues, create_queue, send_queue_message, peek_queue (look without taking), purge_queue, delete_queue, set_queues_api. A queue's table pgmq.q_<name> belongs to the service role and has access rules on. With set_queues_api { exposed: true }, the data API can call it.

await supabase.schema('pgmq_public').rpc('send', { queue_name: 'jobs', message: { hello: 'world' } })
await supabase.schema('pgmq_public').rpc('read', { queue_name: 'jobs', sleep_seconds: 30, n: 5 })

For the publishable key or signed-in users to use it, grant privileges and rules in SQL.

grant insert, select, update on pgmq.q_jobs to authenticated;
create policy "own jobs" on pgmq.q_jobs for all to authenticated using (true) with check (true);

Vault

Encrypts secrets and stores them in vault.secrets in the project's database. The platform holds the key and it is never stored in the database, so dumps, backups and branches hold only ciphertext. A secret opens only when read with the secret key (the service role).

select vault.create_secret('sk_live_...', 'stripe_key', 'Stripe');
select decrypted_secret from vault.decrypted_secrets where name = 'stripe_key';
select vault.update_secret('<id>', 'sk_live_new');

Tools: list_vault_secrets (names only), create_vault_secret, update_vault_secret, delete_vault_secret. The publishable key and signed-in users cannot see the vault schema, and over a direct connection (<ref>_db) decrypted_secret is null.

Move to a dedicated database

Vault and large databases need a dedicated database (from the Pro plan). get_database_move shows where the project is and how its move stands, and move_to_dedicated_database requests the move, as the console's "Move now" does (owners and admins). It moves when its turn comes; writes pause during the move and reads carry on. REST: GET and POST /projects/<ref>/database/move, CLI: oneend db move, oneend db move now.

Dedicated disk

A paid project whose database has grown moves from the disk it shares with other projects to a disk and a Postgres of its own (as Supabase gives each project an instance and a volume). Past 20 GB it moves on its own (an organization without a spend cap, or Enterprise), and Enterprise may ask at any size. The disk starts at max(1.2 x the database, 20 GB), grows by half once it is over 75% full (at most once in 4 hours), and is billed on its provisioned size at KRW 1,200 (75 cents) per GB a month. While it moves writes fail and reads work (expected_downtime_seconds). Connection strings and passwords do not change. Once moved it is restored from its daily backups, not to a point in time.

get_dedicated_disk shows the disk's size, what is used, the monthly cost, 30 days of history and the suggestion to make it smaller; request_dedicated_disk requests the move and shrink_dedicated_disk a smaller disk (owners and admins). A disk is never made smaller on its own: under 25% used for 7 days, a smaller one is suggested, and once confirmed a smaller disk is made, the data moves onto it and the old disk is deleted. When the project is deleted, its disk is deleted 30 days later and costs nothing. REST: GET and POST /projects/<ref>/database/dedicated-disk, POST /projects/<ref>/database/dedicated-disk/shrink, CLI: oneend db disk, oneend db disk request, oneend db disk shrink.

Dedicated server

From Pro, a project can rent a server of its own (the app and the database share it; the database gets 25% of its memory). Sizes and monthly prices per location are list_server_sizes's and are not written here. get_server shows the server, its standby and jobs; request_server (tier, region) rents one; resize_server (tier, when=now|tonight) changes its size (3 to 5 minutes without answers unless there is a standby); set_standby (standby, auto_failover) keeps a standby and fails over after 60 seconds without an answer; move_server (region) moves it (free, once a month, the old server kept 7 days); release_server (confirm=ref) gives it back; set_restore_days (7|28) sets the restore days. After a failed payment it is read-only for 7 days, then backed up and deleted. REST: GET, POST, PATCH, DELETE /projects/<ref>/server, PUT /projects/<ref>/server/standby, POST /projects/<ref>/server/move, PUT /projects/<ref>/server/restore-days. CLI: oneend server, oneend server request|resize|standby|move|release|restore-days.

GraphQL

Turn it on with enable_extension { ref, name: "pg_graphql" } and /graphql/v1 opens. Keys and access rules are the same as /rest/v1.

POST https://<ref>.<zone>/graphql/v1
apikey: <publishable key>
{"query": "{ todosCollection { edges { node { id title } } } }"}

Network restrictions and TLS for direct connections

get_network_restrictions, update_network_restrictions { ref, allowed_cidrs: ["203.0.113.0/24"], enforce_ssl: true }. By default every address is allowed and TLS is required. When the address the request came from is not on the list, it is not saved without confirm: true. The console, the API and run_sql do not go through the connection pooler, so a restriction set by mistake can be undone from there.

Read replicas

Not yet. The standby database (stage 3) is for failover and does not take customer connections.

Over HTTP: GET /queues, POST /queues, POST /queues/<name>/messages, GET /queues/<name>/messages, POST /queues/<name>/purge, DELETE /queues/<name>, PUT /queues/api, GET /vault, POST /vault, PATCH /vault/<name>, DELETE /vault/<name>, GET /network-restrictions, PUT /network-restrictions.