PHPackages                             me-shaon/laravel-resilience - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. me-shaon/laravel-resilience

ActiveLibrary[Testing &amp; Quality](/categories/testing)

me-shaon/laravel-resilience
===========================

Laravel-native fault injection and resilience verification toolkit.

v0.7.0(2mo ago)1132↓90.9%[1 PRs](https://github.com/me-shaon/laravel-resilience/pulls)MITPHPPHP ^8.1CI passing

Since Mar 28Pushed 2mo agoCompare

[ Source](https://github.com/me-shaon/laravel-resilience)[ Packagist](https://packagist.org/packages/me-shaon/laravel-resilience)[ Docs](https://github.com/me-shaon/laravel-resilience)[ GitHub Sponsors](https://github.com/:vendor_name)[ RSS](/packages/me-shaon-laravel-resilience/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (10)Dependencies (26)Versions (13)Used By (0)

Laravel Resilience
==================

[](#laravel-resilience)

Laravel Resilience helps you verify how a Laravel app behaves when a real dependency becomes slow, times out, or fails.

Instead of replacing that dependency with a mock, it injects faults into the actual container-managed service or Laravel integration your code normally uses. That makes it useful for checking fallback behavior, degraded responses, retries, logs, jobs, and duplicate-side-effect protection in a more realistic way.

Why it is useful
----------------

[](#why-it-is-useful)

Use this package when you want to:

- test failure handling against real Laravel wiring, not only mocks
- inject timeouts, exceptions, or latency into real dependency seams
- verify fallback behavior, degraded responses, logs, events, or jobs
- scan an existing codebase for areas that probably need resilience work
- scaffold draft resilience tests from actionable hotspots

In short:

- use mocks for fast unit-level feedback
- use Laravel Resilience for confidence that the real failure path works

Compatibility
-------------

[](#compatibility)

- PHP 8.1+
- Laravel 10, 11, 12, and 13

Installation
------------

[](#installation)

```
composer require me-shaon/laravel-resilience
```

Laravel package discovery registers the service provider and facade automatically.

If you want to customize the defaults:

```
php artisan vendor:publish --tag="laravel-resilience-config"
```

Quick start
-----------

[](#quick-start)

The easiest way to adopt the package is:

1. discover likely resilience-sensitive code
2. turn findings into suggestions
3. scaffold draft tests for the highest-value gaps
4. refine those drafts into real application-specific resilience tests

```
php artisan resilience:discover
php artisan resilience:suggest
php artisan resilience:scaffold
```

What each command does:

- `resilience:discover` finds likely resilience-sensitive code such as HTTP calls, queue dispatches, cache usage, storage writes, and direct client construction
- `resilience:suggest` turns findings into practical next actions such as adding a fallback test, extracting a dependency seam, or tightening duplicate-side-effect protection
- `resilience:scaffold` generates draft Pest tests for actionable hotspots and is safe to rerun

If you want the fuller walkthrough, CLI examples, report options, and longer explanations, read [Usage Guide](guides/usage-guide.md).

The HTML reports are useful when the CLI output gets too large:

```
php artisan resilience:discover --html --preview
php artisan resilience:suggest --html --preview
```

A quick example
---------------

[](#a-quick-example)

Application code:

```
use App\Contracts\PaymentGateway;
use Illuminate\Support\Facades\Log;
use RuntimeException;

final class CheckoutService
{
    public function __construct(
        private PaymentGateway $paymentGateway
    ) {}

    public function charge(int $amount): array
    {
        try {
            $this->paymentGateway->charge($amount);

            return ['status' => 'paid'];
        } catch (RuntimeException $exception) {
            Log::warning('Payment gateway timeout.', [
                'amount' => $amount,
            ]);

            return ['status' => 'retry'];
        }
    }
}
```

Resilience test:

```
use App\Contracts\PaymentGateway;
use Illuminate\Support\Facades\Log;
use MeShaon\LaravelResilience\Facades\Resilience;

Log::spy();

Resilience::for(PaymentGateway::class)->timeout();

$result = app(CheckoutService::class)->charge(500);

Resilience::assertFallbackUsed(
    $result['status'],
    'retry',
    'payment status after gateway timeout'
);

Resilience::assertLogWritten('warning', 'Payment gateway timeout.');

Resilience::deactivateAll();
```

What this proves:

- the real application flow runs
- the real dependency seam is faulted
- your fallback path is exercised under failure
- the outcome is asserted in a readable way

Best fit
--------

[](#best-fit)

Laravel Resilience works best when your app already has clear dependency seams.

Best-supported patterns:

- dependencies resolved through Laravel container bindings
- contracts or interfaces for critical external services
- outbound integrations wrapped in service classes
- isolated side effects in jobs, actions, or dedicated services
- normal Laravel HTTP, mail, cache, queue, and storage entry points

Weakly supported patterns:

- direct `new SomeSdkClient()` calls inside controllers or jobs
- static third-party SDK calls with no container seam
- business logic and IO tightly coupled in the same class

Those areas can still be discovered and suggested, but they usually need some refactoring before fault injection becomes truly effective.

Main capabilities
-----------------

[](#main-capabilities)

### Fault injection

[](#fault-injection)

You can fault container-managed services directly:

```
use App\Contracts\PaymentGateway;
use MeShaon\LaravelResilience\Facades\Resilience;

Resilience::for(PaymentGateway::class)->timeout();
Resilience::deactivateAll();
```

Supported fluent fault types for direct runtime injection:

- `timeout()`
- `exception(Throwable $exception)`
- `latency(int $milliseconds)`

Laravel-aware helpers are also available:

```
Resilience::http()->timeout();
Resilience::mail()->exception(new \RuntimeException('Mail is down.'));
Resilience::cache()->latency(40);
Resilience::queue()->exception(new \RuntimeException('Queue is down.'));
Resilience::storage()->latency(40);
```

Named targets are supported too:

```
Resilience::cache('redis')->latency(40);
Resilience::mail('ses')->exception(new \RuntimeException('SES is down.'));
Resilience::queue('redis')->exception(new \RuntimeException('Redis queue is down.'));
Resilience::storage('s3')->timeout();
```

### Assertions

[](#assertions)

The package includes readable assertions for common resilience outcomes:

- `assertFallbackUsed()`
- `assertLogWritten()`
- `assertEventDispatched()`
- `assertJobDispatched()`
- `assertNoDuplicateSideEffects()`
- `assertDegradedButSuccessful()`

### Scenario runner

[](#scenario-runner)

Scenarios let you define a named resilience drill and run it from Artisan:

```
php artisan resilience:run payment-fallback
php artisan resilience:run payment-fallback --json
php artisan resilience:run payment-fallback --dry-run
```

### Discovery, suggestions, and scaffolding

[](#discovery-suggestions-and-scaffolding)

These commands help teams adopt resilience testing incrementally:

- `resilience:discover` finds likely resilience-sensitive code
- `resilience:suggest` prioritizes actionable follow-up work
- `resilience:scaffold` generates draft Pest tests under `tests/Resilience/Generated`

Scaffold behavior:

- writes a manifest to `build/resilience-scaffold.json`
- skips existing generated files in normal create mode
- avoids overwriting customized generated files in update mode
- only overwrites generated files when you explicitly use `--mode=force`

Safety defaults
---------------

[](#safety-defaults)

Laravel Resilience is intentionally conservative:

- runtime activation is blocked in `production` by default
- scenario execution is only treated as safe by default in `local` and `testing`
- non-local scenario execution requires both `RESILIENCE_ALLOW_NON_LOCAL_SCENARIOS=true` and `--confirm-non-local`
- `--dry-run` lets you inspect a scenario without activating faults

Command reference
-----------------

[](#command-reference)

```
php artisan resilience:run {scenario} [--json] [--dry-run] [--confirm-non-local]
php artisan resilience:discover {path?} [--json] [--category=*] [--compact] [--view=default|compact|verbose] [--html[=path]] [--preview]
php artisan resilience:suggest {path?} [--json] [--category=*] [--include-covered] [--compact] [--view=default|compact|verbose] [--html[=path]] [--preview]
php artisan resilience:scaffold {path?} [--category=*] [--include-covered] [--dry-run] [--mode=create|update|force] [--format=pest] [--output=path] [--manifest=path]
```

Further reading
---------------

[](#further-reading)

If you want the deeper internals and longer examples, use the guides instead of growing the README:

- [Usage Guide](guides/usage-guide.md)
- [How Laravel Resilience Works](guides/how-laravel-resilience-works.md)
- [Example: Well-Structured App](guides/example-well-structured-app.md)
- [Example: Messy Legacy App](guides/example-messy-legacy-app.md)

Development
-----------

[](#development)

```
composer test
composer analyse
composer format
```

License
-------

[](#license)

MIT. See [LICENSE.md](LICENSE.md).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance85

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

11

Last Release

89d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/831997?v=4)[Ahmed shamim](/maintainers/me-shaon)[@me-shaon](https://github.com/me-shaon)

---

Top Contributors

[![me-shaon](https://avatars.githubusercontent.com/u/831997?v=4)](https://github.com/me-shaon "me-shaon (48 commits)")

---

Tags

laravelresiliencereliabilityfault-injection

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/me-shaon-laravel-resilience/health.svg)

```
[![Health](https://phpackages.com/badges/me-shaon-laravel-resilience/health.svg)](https://phpackages.com/packages/me-shaon-laravel-resilience)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k98.0M1.3k](/packages/spatie-laravel-permission)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.3M42](/packages/spatie-laravel-pdf)[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k9.9M90](/packages/dedoc-scramble)[spatie/laravel-health

Monitor the health of a Laravel application

87411.3M153](/packages/spatie-laravel-health)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

43140.3k](/packages/harris21-laravel-fuse)[spatie/laravel-passkeys

Use passkeys in your Laravel app

470755.5k32](/packages/spatie-laravel-passkeys)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
