Skip to content
Back to skills

Upsert Patterns

ASecurity

Insert or update in one statement without races or lost updates, using the engine's conflict handling rather than check-then-write. Use when writing records that may or may not already exist.

  • 7 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 5, 2026
ai-agentssqlapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 5, 2026

npx -y skills add Amey-Thakur/AI-SKILLS --skill upsert-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Upsert Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Upsert Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/amey-thakur-upsert-patterns/badge)](https://www.skillsdirectory.com/skills/amey-thakur-upsert-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: upsert-patterns
description: Insert or update in one statement without races or lost updates, using the engine's conflict handling rather than check-then-write. Use when writing records that may or may not already exist.
---

# Upsert patterns

The naive approach, checking whether a row exists and then inserting or
updating, is a race in every concurrent system: two callers both check,
both find nothing, and one insert fails or duplicates. Upsert exists so
the database resolves that atomically.

## Method

1. **Use the engine's conflict clause.** ON CONFLICT, MERGE, or the
   equivalent performs the decision inside one statement, which is what
   makes it safe under concurrency.
2. **Target a real unique constraint.** Conflict handling needs a
   constraint to detect against, so the uniqueness must exist in the
   schema rather than in your intent.
3. **Decide what update means on conflict.** Overwrite everything, merge
   selected columns, or do nothing. Blindly overwriting can discard
   concurrent changes made between read and write (see
   transactions-isolation).
4. **Preserve creation metadata.** created_at and similar columns should
   not be overwritten by the update branch, which is an easy detail to
   miss and hard to notice later.
5. **Make bulk upserts deterministic.** A batch containing two rows with
   the same key needs a defined winner, since some engines error and
   others pick arbitrarily.
6. **Consider idempotency for retried writes.** An upsert keyed on a
   natural or client-supplied key makes a retried request safe, which is
   what you want in any queue or API path (see idempotency).

## Boundaries

- Upsert resolves existence races; it does not resolve semantic
  conflicts about which version of the data is correct.
- Conflict syntax and behaviour differ substantially between engines, so
  this is one of the less portable parts of SQL.
- Heavy upsert traffic on the same keys creates contention, which is a
  throughput problem rather than a correctness one.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…