Context

When multiple agents touch the same project, speed is never the first problem. Consistency is. If your sync process is non-deterministic, every “fix” creates another hidden branch of state.

Step 1: Add a lock around mutating operations

#!/usr/bin/env bash
set -euo pipefail

LOCK_FILE="/tmp/project-sync.lock"
exec 9>"$LOCK_FILE"
flock -n 9 || { echo "sync already running"; exit 1; }

echo "lock acquired"

Step 2: Use idempotent sync units

Each phase should be safe to rerun after interruption.

type SyncPhase = 'fetch' | 'transform' | 'publish';

async function runPhase(phase: SyncPhase, runId: string) {
  const done = await stateStore.has(`${runId}:${phase}`);
  if (done) return 'skipped';
  await execute(phase);
  await stateStore.mark(`${runId}:${phase}`);
  return 'ok';
}

Step 3: Publish machine-readable run status

{
  "run_id": "sync-20260311-001",
  "started_at": "2026-03-11T00:00:00Z",
  "finished_at": "2026-03-11T00:00:12Z",
  "result": "ok",
  "phases": ["fetch", "transform", "publish"]
}

Step 4: Fail loudly on partial writes

Write outputs to temp locations, validate checksums, then promote atomically.

Pitfalls

  • Two schedulers running the same sync without coordination.
  • No phase checkpointing.
  • Status logs written in prose instead of structured data.

Verification

  • Re-running the same sync ID does not duplicate outputs.
  • Interrupted runs recover without manual data repair.
  • Operators can inspect status with one command.

Get New Tutorials by Email

No spam. Just clear, practical breakdowns you can apply right away.

Enjoy this tutorial?

Get new practical tech tutorials in your inbox.