A Laravel 12 application with intentional production bugs for debugging education.
Warning: This application contains 10 intentional bugs! It's designed for learning how to debug real-world production issues.
NightmareMart is a realistic e-commerce application built with Laravel 12 that demonstrates common production nightmares. Each "episode" focuses on a specific bug pattern that developers encounter in the real world.
| Episode | Bug | Description |
|---|---|---|
| 1 | Config Caching | env() returns null after config:cache |
| 2 | N+1 Queries | Admin orders page triggers thousands of queries |
| 3 | Authorization Hole | Regular users can refund orders |
| 4 | Race Conditions | Two users can buy the last item in stock |
| 5 | Cache Key Collision | Users see each other's cart totals |
| 6 | Memory Leak | Queue worker crashes after ~50 orders |
| 7 | Timezone Nightmare | International users see wrong dates |
| 8 | Log Explosion | Debug logging fills the disk |
| 9 | Search Performance | One search query takes down the site |
| 10 | Money Bug | Floating-point math causes penny discrepancies |
- PHP 8.2+
- Composer 2.6+
- Node.js 20+ (for asset compilation)
- SQLite (default) or MySQL 8.0+
# Clone the repository
git clone <repo-url> nightmare-mart
cd nightmare-mart
# Install PHP dependencies
composer install
# Copy environment file
cp .env.example .env
# Generate application key
php artisan key:generate
# Create SQLite database
touch database/database.sqlite
# Run migrations
php artisan migrate
# Seed the database (creates 10,000+ products, 5,000+ orders)
php artisan db:seed
# Start the development server
php artisan serveAfter seeding, these accounts are available:
| Role | Password | |
|---|---|---|
| Admin | admin@nightmaremart.test | password |
| User | user@nightmaremart.test | password |
- File:
app/Http/Controllers/CheckoutController.php - Line:
$taxRate = env('TAX_RATE', 0.08); - Fix: Use
config('shop.tax_rate')instead
- File:
app/Http/Controllers/Admin/OrderController.php - Symptom: Admin orders page is extremely slow
- Fix: Add eager loading with
->with(['user', 'items.product'])
- File:
routes/web.php - Line:
Route::post('/{order}/refund', ...)->name('refund'); - Fix: Add
->middleware('admin')to the route
- File:
app/Http/Controllers/CheckoutController.php - Symptom: Inventory goes negative under concurrent load
- Fix: Use
lockForUpdate()in a transaction
- File:
app/Services/CartService.php - Line:
Cache::remember('cart_total', ...) - Fix: Scope cache key to user:
"cart_total_{$userId}"
- File:
app/Jobs/GenerateBulkReceiptsJob.php - Symptom: Queue worker crashes with memory exhaustion
- Fix: Use
lazy()orchunk()instead ofget()
- Files: Various views showing
$order->placed_at - Symptom: Dates show in UTC instead of user's timezone
- Fix: Use
$order->placed_at->timezone(auth()->user()->timezone)
- File:
config/logging.php - Symptom: Log file grows to GB in size
- Fix: Use
dailychannel and setLOG_LEVEL=warningin production
- File:
app/Http/Controllers/SearchController.php - Line:
Product::where('name', 'LIKE', "%{$query}%")->get() - Fix: Add pagination, limits, and full-text search indexes
- Files:
CheckoutController.php,OrderCalculator.php - Symptom: Order totals don't match line items
- Fix: Use integer cents, not floating-point dollars
nightmare-mart/
├── app/
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/ # Admin controllers
│ │ │ ├── Auth/ # Authentication
│ │ │ ├── CartController.php
│ │ │ ├── CheckoutController.php # Episodes 1, 4
│ │ │ ├── OrderController.php # Episode 3
│ │ │ └── SearchController.php # Episode 9
│ │ └── Middleware/
│ │ └── IsAdmin.php # Episode 3
│ ├── Jobs/
│ │ └── GenerateBulkReceiptsJob.php # Episode 6
│ ├── Models/ # Eloquent models
│ ├── Policies/
│ │ └── OrderPolicy.php # Episode 3
│ ├── Services/
│ │ ├── CartService.php # Episode 5
│ │ └── OrderCalculator.php # Episode 10
│ └── ValueObjects/
│ └── Money.php # Episode 10 fix
├── config/
│ ├── logging.php # Episode 8
│ └── shop.php # Episode 1
├── database/
│ ├── migrations/
│ ├── factories/
│ └── seeders/
│ └── NightmareMartSeeder.php
├── resources/views/
│ ├── layouts/
│ │ ├── app.blade.php # Main layout
│ │ └── admin.blade.php # Admin layout
│ ├── admin/ # Admin views
│ ├── auth/ # Login/Register
│ ├── cart/
│ ├── checkout/
│ ├── orders/
│ ├── products/
│ └── search/
└── routes/
└── web.php # Episode 3 bug
# Run development server
php artisan serve
# Run queue worker (for Episode 6 testing)
php artisan queue:work
# Clear config cache (Episode 1)
php artisan config:clear
# Cache config (triggers Episode 1 bug)
php artisan config:cache
# Monitor slow queries
php artisan db:monitor
# Fresh migration with seeding
php artisan migrate:fresh --seed- Start with Episode 1 - Understand environment/config basics
- Episode 2 - Learn database query optimization
- Episode 3 - Security and authorization
- Episode 4 - Concurrency and database locking
- Episode 5 - Caching strategies
- Episode 6 - Memory management
- Episode 7 - Datetime/timezone handling
- Episode 8 - Logging best practices
- Episode 9 - Query performance
- Episode 10 - Financial calculations
If using this for video content:
- Install Laravel Debugbar for query visualization
- Use the seeded data (10,000+ products) to demonstrate slowness
- Test accounts with different timezones for Episode 7
- Low-stock products (stock=1) for Episode 4 race conditions
This is an educational project. Feel free to:
- Add more bug scenarios
- Improve the UI
- Add tests that catch the bugs
- Create fix branches for each episode
MIT License - Feel free to use for learning and teaching!
Happy Debugging! 🐛🔍