WendellAdriel/
laravel-idempotency
g4t.io

Laravel Idempotency: HTTP Idempotency Middleware for Laravel

161 stars by Paul Redmond

HTTP Idempotency Middleware for Laravel applications

README from WendellAdriel/laravel-idempotency Open on GitHub →

Installation

You can install the package via composer:

composer require wendelladriel/laravel-idempotency

You can publish the config file with:

php artisan vendor:publish --tag="idempotency"

Usage

Attach the middleware to routes that create or update data:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use WendellAdriel\Idempotency\Http\Middleware\Idempotent;

Route::post('/orders', function (Request $request) {
    return response()->json([
        'id' => 1,
        'item' => $request->input('item'),
    ], 201);
})->middleware(Idempotent::class);

By default, the middleware reads the key from the Idempotency-Key header or the _idempotency_key request input. This allows standard HTML forms to include the key in a hidden input. When both values are present, the header takes precedence.

Use the @idempotency Blade directive to render the hidden input with a generated key:

<form method="POST" action="/orders">
    @csrf
    @idempotency

    <!-- ... -->
</form>

You may pass an existing key with @idempotency($key).

When the same key is sent again with the same request data, the package replays the original response instead of executing your route again.

The HTTP middleware requires a cache driver that supports atomic locks. In multi-server deployments, every application server must use the same shared cache backend. The array driver is only suitable for tests or single-process development. See Laravel's atomic lock documentation for supported deployment options.

Streamed and binary file responses cannot be captured safely, so they are not cached. A repeated request with the same key executes the route again, and the response does not include an Idempotency-Replayed header.

Customize a single route with Idempotent::using:

use WendellAdriel\Idempotency\Enums\IdempotencyScope;
use WendellAdriel\Idempotency\Http\Middleware\Idempotent;

Route::post('/payments', ChargePaymentController::class)->middleware(
    Idempotent::using(
        ttl: 600,
        required: false,
        scope: IdempotencyScope::Ip,
        header: 'X-Idempotency-Key',
        lockTimeout: 30,
        cacheStatuses: ['client_error' => false],
    )
);

The cacheStatuses option controls which response categories are stored: informational, success, redirection, client_error, and server_error. All are enabled by default; disabling one leaves the key free for a retry instead of replaying a stored failure.

You may also use the idempotent middleware alias:

Route::post('/orders', StoreOrderController::class)->middleware('idempotent');

If you prefer attributes, use the package's #[Idempotent] attribute on a controller class or method:

use Symfony\Component\HttpFoundation\Response;
use WendellAdriel\Idempotency\Attributes\Idempotent;

#[Idempotent]
class OrderController
{
    public function store(): Response
    {
        // ...
    }
}

Generate a key in application code when needed:

use WendellAdriel\Idempotency\Idempotency;

$key = Idempotency::key();

Inspect and prune cached entries with the included Artisan commands:

php artisan idempotency:list
php artisan idempotency:forget --key=checkout-1 --force

Access the full documentation here.

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Thank you for considering contributing to Laravel Idempotency! You can read the contribution guide here.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

Laravel Idempotency is open-sourced software licensed under the MIT license.

More from the ecosystem

marcreichel/
laya-php
g4t.io
3 53

LayaPHP: Self-Hosted Text Classification for PHP and Laravel

Classify text in PHP without an LLM bill: typed decisions in 100+ languages, self-hosted. Laravel-ready SDK for Laya, a Jev AI alternative.

ai classification decision-engine
marcreichel/laya-php via Laravel News
Josh-Dovey/
postcodes-laravel
g4t.io
5 9

Postcodes for Laravel: GB Postcode Lookup and Geography Data

Postcodes for Laravel adds typed GB postcode lookups, validation, geography data, distance searches, and test fakes through the GB Postcodes API.

Josh-Dovey/postcodes-laravel via Laravel News
RedberryProducts/
mailbox-for-laravel
g4t.io
4 115

Mailbox for Laravel: Preview and Test Rendered Email

Mailbox for Laravel captures outgoing mail in a local dashboard and lets you test rendered HTML, recipients, and attachments with fluent assertions.

RedberryProducts/mailbox-for-laravel via Laravel News