<?php
declare(strict_types=1);
namespace App\Services\Wallet;
use App\Models\Wallet;
use App\Models\Transaction;
use Illuminate\Support\Facades\DB;
final class AtomicWalletCreditService
{
public function credit(int $userId, float $amount, string $reference): Transaction
{
return DB::transaction(function () use ($userId, $amount, $reference): Transaction {
$wallet = Wallet::where('user_id', $userId)->lockForUpdate()->firstOrFail();
$existing = Transaction::where('reference', $reference)->first();
if ($existing) return $existing;
$wallet->increment('balance', $amount);
return Transaction::create([
'wallet_id' => $wallet->id,
'user_id' => $userId,
'amount' => $amount,
'type' => 'credit',
'reference' => $reference,
'balance_after' => $wallet->balance,
]);
});
}
}
Enterprise Lessons Learnt Building Production Systems with Laravel
Modern Laravel has matured into a powerhouse for enterprise banking, hospital management systems (HMIS), and mission-critical multi-tenant SaaS. Scaling Laravel requires moving beyond default conventions to battle-tested patterns.
The 5 Golden Rules of Scalable Laravel:
- 1. Never perform synchronous network I/O in HTTP controllers.
- 2. Pin platform dependencies strictly in
composer.json. - 3. Use database compound indexes aligned with query selectivity.
- 4. Leverage Read-Replicas for analytics & reporting endpoints.
- 5. Encapsulate business logic inside Invokable Action classes.
1. Concurrency & Locking Strategies
In high-concurrency payment processing, combining DB::transaction() with ->lockForUpdate() prevents race conditions where simultaneous webhooks might credit user balances twice.
Downloadable Slide Decks & Source Assets
Accelerate Your Engineering Career
Get monthly masterclasses, exclusive code snippets, and direct architectural reviews.
Become a Supporter • KES 500 / Month