← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

ACID Properties

General PHP 5.0+ Intermediate
debt(d5/e3/b5/t6)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep and phpstan as tools that can detect multiple related INSERT/UPDATE/DELETE statements without wrapping transactions. This is a pattern-based detection that requires specialist static analysis tooling — default linters won't catch missing transaction boundaries, but SAST tools like semgrep with custom rules can flag the common case of unwrapped multi-step writes.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is 'wrap related database operations in a transaction — if any step fails, rollback ensures the database stays consistent.' This is typically a localized fix within one file or service method — adding BEGIN/COMMIT/ROLLBACK around existing queries. It's more than a one-line patch (e1) since you need to add try/catch logic and rollback handling, but it's a well-understood pattern that doesn't span multiple files in most cases.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). ACID awareness applies across all contexts (web, cli, queue-worker) per the applies_to field. The decision about transaction boundaries and isolation levels is not a one-time architectural choice but a persistent concern: every new feature that touches multiple tables must consider transactional wrapping, and choosing the wrong default isolation level has systemic implications. It doesn't quite define the system's shape (b9) but it does slow down many work streams as developers must consistently reason about transaction boundaries.

t6 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5), scored +1 to t6. The misconception states that 'All databases claiming ACID compliance provide the same guarantees' — this is a significant trap because developers commonly assume ACID is binary (you have it or you don't), when in reality isolation levels (READ COMMITTED vs REPEATABLE READ vs SERIALIZABLE) vary dramatically in behavior. Additionally, common_mistakes include assuming NoSQL databases are ACID and using READ UNCOMMITTED. This goes slightly beyond a 'documented gotcha most devs eventually learn' (t5) because the trap involves multiple layers of false confidence — believing you have ACID, not understanding which isolation level you're running, and not realizing different engines behave differently under the same ACID label.

About DEBT scoring →

Also Known As

ACID atomicity consistency isolation durability database transactions ACID

TL;DR

The four guarantees of database transactions: Atomicity, Consistency, Isolation, and Durability.

Explanation

ACID ensures reliable transaction processing: Atomicity — a transaction either fully succeeds or fully rolls back (no partial writes); Consistency — the database moves from one valid state to another, enforcing constraints; Isolation — concurrent transactions don't see each other's intermediate state (controlled by isolation levels: Read Uncommitted, Read Committed, Repeatable Read, Serializable); Durability — committed transactions survive crashes (via write-ahead logging). In PHP, manage transactions explicitly with PDO::beginTransaction(), commit(), and rollBack(), especially when multiple related writes must succeed together.

Diagram

flowchart TD
    subgraph ACID
        A[Atomicity<br/>all or nothing<br/>no partial writes]
        C[Consistency<br/>business rules<br/>always maintained]
        I[Isolation<br/>concurrent transactions<br/>don't interfere]
        D[Durability<br/>committed data<br/>survives crashes]
    end
    TRANS[Database Transaction] --> A & C & I & D
    FAIL[Power failure<br/>during write] -->|redo log| D
    CONC[Concurrent writes] -->|locks + MVCC| I
style A fill:#238636,color:#fff
style C fill:#238636,color:#fff
style I fill:#1f6feb,color:#fff
style D fill:#6e40c9,color:#fff

Common Misconception

All databases claiming ACID compliance provide the same guarantees. ACID isolation levels vary — READ COMMITTED, REPEATABLE READ, and SERIALIZABLE offer progressively stronger guarantees with progressively higher overhead. "ACID compliant" without specifying the default isolation level is meaningless.

Why It Matters

ACID guarantees that database transactions are reliable — without them, concurrent writes can corrupt data, partial failures can leave data in inconsistent states, and reads can see uncommitted changes.

Common Mistakes

  • Assuming NoSQL databases are ACID — most sacrifice isolation or durability for performance.
  • Not wrapping multi-step operations in a transaction — a crash between steps leaves data inconsistent.
  • Using READ UNCOMMITTED isolation — allows dirty reads of data that may be rolled back.
  • Relying on application-level locking instead of database transactions for concurrency.

Avoid When

  • You need horizontal scalability across distributed nodes — full ACID across shards requires coordination overhead.
  • The workload tolerates eventual consistency — sacrificing isolation for availability (BASE model) may be correct.
  • Using NoSQL stores that offer only document-level atomicity — do not assume full ACID without verifying.

When To Use

  • Financial transactions, inventory management, or any domain where partial writes are catastrophic.
  • Any operation touching multiple rows or tables that must succeed or fail atomically.
  • Concurrent workloads where isolation prevents dirty reads and phantom reads.
  • Systems where durability guarantees are required — data must survive a crash without loss.

Code Examples

✗ Vulnerable
// Two separate queries without a transaction — partial failure leaves inconsistent state
$pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
$pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
✓ Fixed
try {
  $pdo->beginTransaction();
  $pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
  $pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
  $pdo->commit();
} catch (Exception $e) {
  $pdo->rollBack(); throw $e;
}

Added 15 Mar 2026
Edited 25 Mar 2026
Views 91
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 3 pings T 3 pings F 2 pings S 5 pings S 4 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 1 ping S 1 ping S 0 pings M 1 ping T 0 pings W
No pings yet today
Claude 1
Amazonbot 15 Scrapy 15 Perplexity 10 Google 6 SEMrush 6 Ahrefs 5 Unknown AI 3 Claude 3 Bing 3 Qwen 1 Meta AI 1 PetalBot 1
crawler 64 crawler_json 4 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Wrap related database operations in a transaction — if any step fails, rollback ensures the database stays consistent; never leave partial writes committed
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Multiple related INSERT/UPDATE/DELETE statements without wrapping transaction; partial write possible on error
Auto-detectable: ✓ Yes semgrep phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: File Tests: Update


✓ schema.org compliant