idempotency

star 126

Install, configure, and apply the Laravel Idempotency package in Laravel applications when you need retry-safe POST, PUT, or PATCH endpoints.

WendellAdriel By WendellAdriel schedule Updated 4/22/2026

name: idempotency description: > Install, configure, and apply the Laravel Idempotency package in Laravel applications when you need retry-safe POST, PUT, or PATCH endpoints.

Idempotency

Use this skill when a Laravel application needs retry-safe write requests, idempotency keys, or controller attributes.

Primary Goal

  • install and configure wendelladriel/laravel-idempotency correctly
  • choose the smallest correct integration path for the app
  • apply middleware, attributes, and scopes using the package's public API

Workflow

1. Inspect the Laravel app context

  • confirm the app is a Laravel project
  • inspect the target routes or controllers that create or update data
  • identify whether the endpoint is better served by route middleware or a controller attribute
  • inspect the app cache driver when idempotency will be enabled in production, since atomic locks are required

2. Install and publish configuration when needed

  • install the package with composer require wendelladriel/laravel-idempotency
  • publish the config with php artisan vendor:publish --tag=idempotency-config when the app needs non-default behavior
  • use these config keys when customization is required:
    • idempotency.ttl
    • idempotency.required
    • idempotency.scope
    • idempotency.header

3. Choose the integration style

Prefer route middleware when:

  • only a few endpoints need idempotency
  • the behavior belongs directly on a route definition
  • the app already configures most middleware in the route files

Use the controller attribute when:

  • the app groups related write actions inside a controller
  • class-level defaults with method-level overrides make the intent clearer
  • only or except targeting is useful

4. Apply route middleware

Use the package middleware class:

use WendellAdriel\Idempotency\Http\Middleware\Idempotent;

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

When the endpoint needs overrides, use Idempotent::using(...):

Route::post('/payments', ChargePaymentController::class)
    ->middleware(Idempotent::using(
        ttl: 600,
        required: false,
        scope: \WendellAdriel\Idempotency\Enums\IdempotencyScope::Ip,
        header: 'X-Idempotency-Key',
    ));

5. Apply the controller attribute

Use the package attribute on classes or methods:

use WendellAdriel\Idempotency\Attributes\Idempotent;

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

Use method-level attributes to override class-level defaults:

use WendellAdriel\Idempotency\Enums\IdempotencyScope;

#[Idempotent]
class PaymentController
{
    #[Idempotent(ttl: 600, scope: IdempotencyScope::Global)]
    public function store()
    {
        // ...
    }
}

6. Choose the correct scope

  • use user when authenticated users should not collide with each other; guests fall back to IP
  • use ip for guest-heavy flows where IP segmentation is enough
  • use global when the same key should replay across users or IPs

7. Support key generation

  • generate a random key in app code with WendellAdriel\Idempotency\Idempotency::key() when the server needs to create keys

8. Verify the integration

  • verify repeated POST, PUT, or PATCH requests with the same key replay the original response
  • verify mismatched payloads return 422
  • verify in-flight duplicate requests return 409 with Retry-After: 1
  • verify missing headers only pass through when required is disabled

9. Maintain cached entries

Use the maintenance commands when debugging replay behavior, purging entries after a compromised key, or inspecting cache usage during incident response.

  • inspect cached entries with php artisan idempotency:list
  • filter listings by scope or identity when the cache is large:
php artisan idempotency:list --scope=user --id=5
php artisan idempotency:list --scope=global
php artisan idempotency:list --limit=20
  • purge entries when replay behavior is the wrong thing to keep:
# remove everything (prompts unless --force is passed)
php artisan idempotency:forget --all --force

# scoped removal
php artisan idempotency:forget --scope=user --id=5 --force
php artisan idempotency:forget --scope=ip --id=1.2.3.4 --force
php artisan idempotency:forget --scope=global --force

# purge everything tied to a single client-provided key
php artisan idempotency:forget --key=checkout-1 --force

Rules, References, and Templates

Read before executing:

  • no additional resource files for this skill

Examples

  • add idempotency to payment or order creation endpoints
  • protect retryable webhook receivers

Anti-patterns

  • do not apply idempotency to read-only routes
  • do not suggest unsupported scope values beyond user, ip, and global
  • do not document package maintenance tasks here; keep the skill focused on package adoption in Laravel apps
  • do not assume every production cache driver supports atomic locks without checking
Install via CLI
npx skills add https://github.com/WendellAdriel/laravel-idempotency --skill idempotency
Repository Details
star Stars 126
call_split Forks 5
navigation Branch main
article Path SKILL.md
More from Creator
WendellAdriel
WendellAdriel Explore all skills →