Laravel Deadlock: Manage Technical Debt with Expiring Code Markers
Every developer has encountered scenarios where they write code intended to be temporary—a quick workaround before a demo, a feature flag for a gradual rollout, or a placeholder while waiting for a vendor fix. However, the problem arises when TODO comments get buried, tickets get forgotten, and “temporary” code becomes permanent. This is where Laravel Deadlock, a package developed by Med Mahmoud Hdaya, steps in to help manage technical debt effectively.
Understanding Laravel Deadlock
Laravel Deadlock is designed to help developers manage temporary code by allowing them to mark workarounds with explicit expiration dates using PHP attributes. This package enforces accountability by throwing runtime exceptions in development and causing build failures in CI/CD pipelines when deadlines pass. By implementing Laravel Deadlock, teams can ensure that temporary solutions do not linger indefinitely, thus keeping the codebase clean and maintainable.
How It Works
The core functionality of Laravel Deadlock revolves around marking code for review and enforcing deadlines. Below, we will explore how to use this package effectively.
Marking Code for Review
To mark a piece of code as a temporary workaround, you can use the #[Workaround] attribute. This attribute allows you to include a description of why the code is temporary and set an expiration date. Here’s an example of how to mark a controller method during an API migration:
use ZidbihDeadlockAttributesWorkaround;
class PaymentController extends Controller {
#[Workaround(description: 'Using old Stripe API v2 until upgrade to v3 is complete', expires: '2026-01-05')]
public function processPayment(Request $request) {
// Temporary workaround using legacy API
return $this->legacyStripeService->charge($request->amount);
}
}You can also mark entire classes, which is particularly useful for feature flags or deprecated code paths:
use ZidbihDeadlockAttributesWorkaround;
#[Workaround(description: 'Remove legacy dashboard after all users migrated', expires: '2026-02-15')]
class LegacyDashboardController extends Controller {
// Old dashboard implementation to be removed
}Listing Workaround Code
To audit all temporary code in your project, you can run the following command:
php artisan deadlock:listThis command will output a table that helps teams systematically track technical debt:
+---------+------------+-------------------------------------+---------------------------------------------------+
| Status | Expires | Location | Description |
+---------+------------+-------------------------------------+---------------------------------------------------+
| EXPIRED | 2026-01-05 | PaymentController::processPayment | Using old Stripe API v2 until upgrade to v3 |
| OK | 2026-02-15 | LegacyDashboardController | Remove legacy dashboard after all users migrated |
| OK | 2026-01-20 | CacheAdapter::get | Temporary Redis workaround until cache driver fix |
+---------+------------+-------------------------------------+---------------------------------------------------+This command provides a clear view of what needs attention during sprint planning or code review.
Enforcing Deadlines
Laravel Deadlock distinguishes between development and production environments. In local development, executing code with an expired deadline throws an exception, blocking further progress until the team either extends the deadline or resolves the underlying issue. In production, however, runtime enforcement is disabled to ensure users never experience interruptions.
To automate enforcement in CI/CD pipelines, you can integrate the check command into your workflow. Below is an example of how to set this up in a GitHub Actions workflow:
# .github/workflows/tests.yml
name: Tests
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Checkout Code
uses: actions/checkout@v4.1.7
- name: Install dependencies
run: composer install
- name: Check for expired deadlocks
run: php artisan deadlock:check
- name: Run tests
run: php artisan test
If any workaround code has expired, the build will fail with exit code 1, preventing deployment until the team addresses the technical debt. The output will indicate which workarounds have expired, prompting immediate action.
Runtime Enforcement for Services
While controllers are automatically checked for expired workarounds, services and other classes require explicit enforcement. You can use the DeadlockGuard::check() method to trigger expiration checks when the class is instantiated:
use ZidbihDeadlockAttributesWorkaround;
use ZidbihDeadlockSupportDeadlockGuard;
#[Workaround(description: 'Temporary legacy pricing logic', expires: '2026-02-01')]
final class PricingService {
public function __construct() {
DeadlockGuard::check($this);
}
}For method-level enforcement, you can pass the method name as a second argument:
DeadlockGuard::check($this, __FUNCTION__);Practical Use Cases
Laravel Deadlock is particularly effective in several common scenarios:
- Feature Flag Removal: Mark feature flags with deadlines tied to rollout completion dates.
- API Migration Paths: Track temporary adapters or compatibility layers during vendor upgrades.
- Deprecated Functionality: Set deadlines for removing old code after user migrations are complete.
- Post-launch Cleanup: Mark quick fixes made during production incidents with follow-up dates.
- Time-boxed Experiments: Give experimental features explicit expiration dates for evaluation periods.
Installation and Compatibility
To install Laravel Deadlock, you can use Composer with the following command:
composer require zidbih/laravel-deadlockThe package requires PHP 8.2 or higher and is compatible with Laravel versions 10, 11, and 12. For full documentation and to view the source code, you can check out the GitHub repository.
Frequently Asked Questions
Laravel Deadlock is a package that helps developers manage temporary code by allowing them to mark workarounds with explicit expiration dates. It enforces accountability by throwing exceptions in development and causing build failures in CI/CD pipelines when deadlines pass.
You can mark temporary code by using the #[Workaround] attribute, which allows you to include a description and set an expiration date for the code. This helps in tracking technical debt effectively.
In local development, Laravel Deadlock throws exceptions for expired deadlines, blocking progress until the issue is resolved. In production, runtime enforcement is disabled to avoid user interruptions, but CI/CD pipelines can be set up to check for expired workarounds automatically.
Call To Action
Take control of your technical debt today by implementing Laravel Deadlock in your projects. Ensure that temporary solutions do not linger and keep your codebase clean and maintainable.
Note: Managing technical debt is crucial for maintaining a healthy codebase. Laravel Deadlock provides an effective way to ensure that temporary code is addressed in a timely manner, helping teams maintain high-quality software.

