Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Postgres performance optimization and best practices guide maintained by Supabase
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/data-upsert.md
1---2title: Use UPSERT for Insert-or-Update Operations3impact: MEDIUM4impactDescription: Atomic operation, eliminates race conditions5tags: upsert, on-conflict, insert, update6---78## Use UPSERT for Insert-or-Update Operations910Using separate SELECT-then-INSERT/UPDATE creates race conditions. Use INSERT ... ON CONFLICT for atomic upserts.1112**Incorrect (check-then-insert race condition):**1314```sql15-- Race condition: two requests check simultaneously16select * from settings where user_id = 123 and key = 'theme';17-- Both find nothing1819-- Both try to insert20insert into settings (user_id, key, value) values (123, 'theme', 'dark');21-- One succeeds, one fails with duplicate key error!22```2324**Correct (atomic UPSERT):**2526```sql27-- Single atomic operation28insert into settings (user_id, key, value)29values (123, 'theme', 'dark')30on conflict (user_id, key)31do update set value = excluded.value, updated_at = now();3233-- Returns the inserted/updated row34insert into settings (user_id, key, value)35values (123, 'theme', 'dark')36on conflict (user_id, key)37do update set value = excluded.value38returning *;39```4041Insert-or-ignore pattern:4243```sql44-- Insert only if not exists (no update)45insert into page_views (page_id, user_id)46values (1, 123)47on conflict (page_id, user_id) do nothing;48```4950Reference: [INSERT ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT)51