concurrency-and-async

concurrency-and-async is a skill for Claude Code, Codex from tmj-90/gaffer. It costs 108 tokens per session (2,151 once invoked), scanned A, original, Apache-2.0.

A guide for code that does more than one thing at the same time, such as asynchronous requests, threads, background tasks, or goroutines. It focuses on shared data, ordering, limits, cancellation, and safe handling of failures.

In plain words
What is it for?
Use it for async/await flows, promises, futures, worker pools, locks, channels, parallel requests, and intermittent double-processing bugs.
Why use it?
It helps prevent race conditions, deadlocks, duplicate processing, and other bugs that may appear only when operations overlap.

Skill for Claude CodeCodex

Written for no agent in particular: nothing here depends on one.

Good fit Use it for async/await flows, promises, futures, worker pools, locks, channels, parallel requests, and intermittent double-processing bugs.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/tmj-90/gaffer/concurrency-and-async
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.

Any agent
npx skills add tmj-90/gaffer --skill concurrency-and-async
Clone the repo
git clone --depth 1 https://github.com/tmj-90/gaffer

Made for: Claude Code, Codex.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for concurrency-and-async

README.md
[![agentmods](https://agentmods.dev/badge/skills/tmj-90/gaffer/concurrency-and-async/github.svg)](https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async)
Your own site
<a href="https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/concurrency-and-async/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for concurrency-and-async

Your own site · 80×15
<a href="https://agentmods.dev/skills/tmj-90/gaffer/concurrency-and-async"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/concurrency-and-async.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 108 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 2,151 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
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.1 $0.00108 $0.02151
Opus 5.5 $0.00043 $0.00860
Sonnet 5.5 $0.00022 $0.00430
Haiku 4.5 $0.00011 $0.00215

Measured 16d ago against content hash 9ecde85367e7, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

concurrency-and-async 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 16d 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.

runner/skills/concurrency-and-async/SKILL.md · 130 lines

How it starts

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

Write concurrent code that is correct under interleaving

Concurrency bugs pass every sequential test. Live builds of the same app twice shipped the same class past review: fixed temp-file names colliding under parallel requests (HTTP 500), unsynchronised read-modify-write losing updates, and a time-only stale-lock lease that dropped an acknowledged write when the holder was paused past the threshold. Assume that any code with a shared file, row, counter or lock has one of these until a test that forces the schedule proves otherwise.

Steps

  1. Inventory shared state and writers. For every file, row, counter, cache entry or lock file the change touches, list who can write it: concurrent requests in one async process (every await is a yield point), threads, other worker processes or instances, and a restarted process after a crash. Call search_lore for the repo's lock helper, worker model and transaction rules. Each item must end up immutable, single-owner (one queue/actor/goroutine does all writes), or guarded.
  2. Pick the guard by scope. In one process: a mutex or per-key async lock, or a single-writer queue. Across processes on one host: an OS lock the kernel releases on death (flock/fcntl, LockFileEx). Across hosts or on database rows: the database (UPDATE … SET n = n + 1, SELECT … FOR UPDATE, a unique constraint, a version column, pg_advisory_xact_lock). An in-memory flag guards nothing once there are two processes.
  3. Serialise every read-modify-write. Read → compute → write with no guard loses updates. Use one atomic statement; or compare-and-swap (UPDATE t SET v = v + 1, data = ? WHERE id = ? AND v = ?, check the affected row count, retry a bounded number of times, then 409); or hold one lock across the whole read, modify and write. A lock around only the write does not help. Check-then-act across an await (if (!exists) await create()) is the same bug.
  4. Write files atomically. Create the temp file in the same directory with a unique name (mkstemp, os.CreateTemp, O_CREAT|O_EXCL, or pid + random suffix — never a fixed data.json.tmp or a timestamp), write, fsync it when the data must survive power loss, rename over the target (os.replace in Python), then fsync the directory for a durable rename; delete the temp on failure. Use a library such as write-file-atomic (Node) or renameio (Go) only if it is already a dependency; never install one. Rename gives readers old-or-new, never a torn file — it does not serialise writers, so step 3 still applies. Acknowledge (2xx, return success) only after the rename, and after the fsyncs when durability is the contract.
  5. Make cross-process locks safe against pauses. A process can stop for seconds without dying: GC, SIGSTOP, VM suspend, swap, a debugger. A lock declared stale because of age alone is then stolen while its holder still believes it owns it; the holder resumes and overwrites the new owner's acknowledged write. In order of preference:
    • a kernel-held lock (flock/fcntl) released when the owner process dies and never because time passed; or a Postgres advisory lock taken on the same connection or transaction that performs every guarded write (pg_advisory_xact_lock). Postgres releases it whenever the session ends (idle timeout, dropped connection, pooler), so it protects only writes made through that session — never a file or another store;
    • an owner-liveness check: the lock records pid, host and process start time or a nonce, and is broken only when that owner is provably gone — same host, and either kill(pid, 0) fails with ESRCH or the process now running under that pid has a different start time (pid reuse). EPERM only means some process holds that pid: compare its start time, and never treat EPERM alone as gone. Age may trigger the check, never decide it;
    • a fencing token when a time lease is unavoidable (distributed lock, job lease): each grant returns a monotonically increasing number, every write carries it, and the resource rejects a token lower than the highest it has accepted. "Re-check I still hold the lock, then write" is not a substitute (unless the check takes a row lock held until the write commits, as in the scheduled-jobs skill); the pause can land between check and write.

Read the full file on GitHub · 130 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. 16d ago Changed · +63 lines · +21 tokens per session 9ecde85367e7
  2. 19d ago First seen · 67 lines · 87 tokens per session scan A 411e39e47749

Subscribe to this mod's changes

concurrency-and-async is a skill published in the GitHub repository tmj-90/gaffer (2 stars, last pushed 17d ago), licensed Apache-2.0. It adds 108 tokens to every session and 2,151 once invoked, about $0.0004 per session on Opus 5.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-09-28.