All skills
asyrafhussin avatar

/laravel-database-optimization

@ac26821

Laravel database optimization patterns. Use when writing Eloquent queries, creating migrations, configuring caching, debugging slow queries, or optimizing database performance. Triggers on tasks involving N+1 queries, indexing, Redis caching, pagination, or database transactions.

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/laravel-database-optimization

This session only. Nothing lands on disk.

ruleslock-deadlock-retry.md

≈729 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Use Transaction Retry for Deadlocks

Impact: HIGH (Automatically recovers from transient deadlocks instead of crashing the request)

Deadlocks occur when two or more transactions hold locks that the other needs, creating a circular wait. The database resolves this by killing one transaction. Without retry logic, that killed transaction throws an exception and fails the user's request — even though a simple retry would succeed immediately.

Incorrect

// ❌ No retry — a single deadlock crashes the entire request
DB::transaction(function (): void {
    $sender = Account::where('id', $senderId)->lockForUpdate()->first();
    $receiver = Account::where('id', $receiverId)->lockForUpdate()->first();

    $sender->decrement('balance', $amount);
    $receiver->increment('balance', $amount);
});

// If another request locks these accounts in reverse order, one transaction
// is killed by the database with: "Deadlock found when trying to get lock"
// The request returns a 500 error to the user

Problems:

  • A transient deadlock causes a permanent request failure with no recovery
  • Deadlocks are normal under concurrent load — they are not bugs, they are expected
  • Users see intermittent 500 errors that disappear on retry, undermining trust

Correct

// ✅ Second argument to DB::transaction() sets the retry count
DB::transaction(function (): void {
    $sender = Account::where('id', $senderId)->lockForUpdate()->first();
    $receiver = Account::where('id', $receiverId)->lockForUpdate()->first();

    $sender->decrement('balance', $amount);
    $receiver->increment('balance', $amount);
}, attempts: 3);

// If a deadlock occurs, Laravel automatically retries the entire closure
// up to 3 times before throwing the exception

// ✅ Consistent lock ordering to minimize deadlocks in the first place
DB::transaction(function () use ($senderId, $receiverId, $amount): void {
    // Always lock in ascending ID order to prevent circular waits
    $ids = collect([$senderId, $receiverId])->sort()->values();

    $accounts = Account::whereIn('id', $ids)
        ->lockForUpdate()
        ->orderBy('id')
        ->get()
        ->keyBy('id');

    $accounts[$senderId]->decrement('balance', $amount);
    $accounts[$receiverId]->increment('balance', $amount);
}, attempts: 3);

Benefits:

  • Automatic recovery from transient deadlocks without user-facing errors
  • The attempts parameter is built into Laravel's DB::transaction() — no external packages needed
  • Consistent lock ordering combined with retry makes deadlocks rare and survivable

Reference: Laravel Database Transactions

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill is a comprehensive documentation set for optimizing database performance in Laravel 13 applications. It provides best practices for Eloquent queries, indexing, Redis caching, and safe migrations. No malicious patterns, prompt injections, or data exfiltration attempts were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    6/39 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at ac26821. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
metadata
{
  "author": "agent-skills",
  "version": "1.1.1"
}

README badge

README badge for asyrafhussin/agent-skills/laravel-database-optimization