convex-write-conflicts

Rules for preventing conflicting data updates in React applications that use Convex. A write conflict happens when simultaneous operations try to change the same stored data, and React is a tool for building interactive web interfaces.

In plain words
What is it for?
Designing Convex mutations, React effects, and rapid user actions so concurrent updates are less likely to conflict or produce errors.
Why use it?
It helps prevent repeated retries and failed updates when several actions run at once. It emphasizes making updates safe to repeat and handling missing or already-completed records.

Cursor rule for Cursor

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add rules/waynesutton/markdown-site/convex-write-conflicts
Clone the repo
git clone --depth 1 https://github.com/waynesutton/markdown-site

Made for: Cursor.

Per session 5,192 This file is loaded in full into every session.
When invoked 5,192 The same file — it is already loaded in full.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.05192 $0.05192
Opus 5 $0.02596 $0.02596
Sonnet 5 $0.01038 $0.01038
Haiku 4.5 $0.00519 $0.00519

Measured 2d ago against content hash e37986b48188, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade A, and why

convex-write-conflicts scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.cursor/rules/convex-write-conflicts.mdc · 777 lines

How it starts

The opening of the file, as written. The whole thing — 777 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Preventing Write Conflicts in Convex with React

Write conflicts occur when two functions running in parallel make conflicting changes to the same table or document. This rule provides patterns to avoid these conflicts.

Understanding Write Conflicts

According to Convex documentation, write conflicts happen when:

  1. Multiple mutations update the same document concurrently
  2. A mutation reads data that changes during execution
  3. Mutations are called more rapidly than Convex can execute them

Convex uses optimistic concurrency control and will retry mutations automatically, but will eventually fail permanently if conflicts persist.

Backend Protection: Idempotent Mutations

Always Make Mutations Idempotent

Mutations should be safe to call multiple times with the same result.

Good Pattern:

export const completeTask = mutation({
  args: { taskId: v.id("tasks") },
  returns: v.null(),
  handler: async (ctx, args) => {
    const task = await ctx.db.get(args.taskId);

    // Early return if document doesn't exist
    if (!task) {
      return null;
    }

    // Early return if already in desired state
    if (task.status === "completed") {
      return null;
    }

    // Only update if state change is needed
    await ctx.db.patch(args.taskId, {
      status: "completed",
      completedAt: Date.now(),
    });

    return null;
  },
});

Bad Pattern:

// This will cause conflicts if called multiple times rapidly
export const completeTask = mutation({
  args: { taskId: v.id("tasks") },
  returns: v.null(),
  handler: async (ctx, args) => {
    const task = await ctx.db.get(args.taskId);
    // No check if already completed
    await ctx.db.patch(args.taskId, {
      status: "completed",
      completedAt: Date.now(),
    });
    return null;
  },
});

Avoid Unnecessary Reads - Patch Directly

When you only need to update fields, patch directly without reading first. Database operations throw if the document doesn't exist.

Read the full file on GitHub · 777 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 2d ago First seen · 777 lines · 5,192 tokens per session scan A e37986b48188

Subscribe to this mod's changes

convex-write-conflicts is a cursor rule published in the GitHub repository waynesutton/markdown-site (631 stars, last pushed 3mo ago), licensed MIT. It adds 5,192 tokens to every session, about $0.0260 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.