Laravel API Versioning: Strategies
Laravel API Versioning: Strategies
Laravel API Versioning: Strategies
Tip: URL-Based Versioning
Route::prefix('v1')->group(function () {
Route::get('/users', [V1\UserController::class, 'index']);
});
Simplest approach — version in the URL.
Gotcha: Header-Based Versioning
Route::middleware('api.version')->group(function () {
// Version determined by middleware
});
Cleaner URLs but harder to test and cache.
Tip: API Resources per Version
Each version has its own resource transformer class.
Gotcha: Breaking Changes
Never change existing API behavior. Add new fields or endpoints instead.
Tip: Sunset Header
return response()->json($data)
->header('Sunset', '2025-12-31')
->header('Deprecation', 'true');
Gotcha: Version Fallback
Consider supporting a default version when none is specified, but log a deprecation warning.
Tip: Use route:cache Carefully
php artisan route:cache is fast, but it doesn't work with closure-based routes. Every time you cache routes, Laravel serializes them. If you have Route::redirect() or closure callbacks, the cache breaks. Stick to controller-based routes in production.
Tip: Model APP_KEY Rotation
Rotating APP_KEY invalidates all encrypted data — cookies, encrypted DB columns, and password reset tokens. If you must rotate (e.g., after a leak), plan a migration that re-encrypts existing data with the new key.
Gotcha: Local Scope Leaks
Global scopes defined in booted() apply to ALL queries on that model — including relationships. An innocent User::all() in admin panel might exclude soft-deleted users if a global scope is active.
Senior Insight
API design is where framework knowledge meets engineering discipline. The mistake I see most often is versioning through URLs (/api/v1/) instead of through content negotiation or headers. URL versioning locks you into maintaining parallel route files forever. I've also learned the hard way that API Resources should use ::$wrap = false to avoid the data envelope when your frontend team doesn't expect it — align on contract format before writing a single endpoint.
Source: Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/laravel), Spatie Blog (https://spatie.be/blog)