← Back to list

Build Scalable REST APIs with Laravel: A Production Guide by Riad Hasan

Modern applications depend on APIs. Whether you’re building SaaS platforms, mobile applications, AI systems, or dashboards, your backend…

Riad Hasan · 2026-05-20 12:29 · 0 claps · 7.3 min read
#riadhasan #laravel #api
Open on Medium ↗
Wiki topics: 🌐 · Web Development 📱 · Mobile Development 🎬 · Film & Television

Build Scalable REST APIs with Laravel: A Production Guide by Riad Hasan

Modern applications depend on APIs. Whether you’re building SaaS platforms, mobile applications, AI systems, or dashboards, your backend API architecture determines scalability, performance, and long-term maintainability.

In this guide, you’ll learn how to build production-ready REST APIs with Laravel using clean architecture, authentication, caching, queues, rate limiting, and performance optimization techniques.

I’m Riad Hasan, a full stack developer who has built scalable APIs for SaaS products, dashboards, e-commerce platforms, and AI-powered applications. Here’s the architecture and workflow that actually works in production.

Why API Architecture Matters

Many developers can build APIs that work locally.

Very few build APIs that:

  • Scale under heavy traffic
  • Stay maintainable after months
  • Handle failures gracefully
  • Remain secure in production
  • Deliver consistent performance

A poorly structured API becomes expensive to maintain.

A properly designed API becomes the backbone of scalable applications.

The Stack

The stack Riad Hasan uses for scalable Laravel APIs:

LayerTechnologyBackend FrameworkLaravelAuthenticationLaravel SanctumDatabaseMySQL / PostgreSQLCacheRedisQueue SystemRedis QueuesAPI TestingPestMonitoringTelescope / SentryDeploymentNginx + Supervisor

API Architecture Overview

The structure looks like this:

Client App
   ↓
Laravel API
   ↓
Service Layer
   ↓
Repository Layer
   ↓
Database / Cache / Queue

This separation keeps the application clean and scalable.

Step 1: Create a Clean API Structure

Instead of placing all logic inside controllers, Riad Hasan separates concerns properly.

Example Structure

app/
├── Http/
│   ├── Controllers/Api
│   ├── Requests
│   └── Resources
├── Services
├── Repositories
├── Jobs
└── Models

Step 2: API Authentication with Sanctum

Install Sanctum:

composer require laravel/sanctum

Publish migrations:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

User Model

use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
    use HasApiTokens;
}

Login Endpoint

public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);
    if (!Auth::attempt($credentials)) {
        return response()->json([
            'message' => 'Invalid credentials'
        ], 401);
    }
    $user = Auth::user();
    $token = $user->createToken('api-token')->plainTextToken;
    return response()->json([
        'token' => $token,
        'user' => $user,
    ]);
}

Step 3: Use Form Requests for Validation

Riad Hasan avoids validation inside controllers.

Create Request

php artisan make:request StorePostRequest

Validation Rules

class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => 'required|max:255',
            'content' => 'required',
            'status' => 'required|in:draft,published',
        ];
    }
}

Controller

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());
    return new PostResource($post);
}

Cleaner, reusable, and production-ready.

Step 4: API Resources for Consistent Responses

Never return raw models directly.

Resource Example

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'author' => [
                'name' => $this->author->name,
            ],
            'created_at' => $this->created_at->toISOString(),
        ];
    }
}

This gives full control over API responses.

Step 5: Use Service Layer Architecture

Controllers should stay thin.

Bad Controller

public function store(Request $request)
{
    // validation
    // database logic
    // notifications
    // queue jobs
    // caching
}

Good Controller

public function store(StorePostRequest $request)
{
    $post = $this->postService->create($request->validated());
    return new PostResource($post);
}

Service Example

class PostService
{
    public function create(array $data): Post
    {
        $post = Post::create($data);
        ProcessPostJob::dispatch($post);
        return $post;
    }
}

Step 6: Add Redis Caching

Caching dramatically reduces database load.

Install Redis

CACHE_DRIVER=redis
QUEUE_CONNECTION=redis

Cache Expensive Queries

$posts = Cache::remember('featured_posts', 3600, function () {
    return Post::with('author')
        ->where('featured', true)
        ->latest()
        ->take(10)
        ->get();
});

Riad Hasan uses Redis heavily in production APIs to reduce repeated queries.

Step 7: Queue Heavy Operations

Never send emails or process heavy tasks during requests.

Create Job

php artisan make:job SendWelcomeEmail

Dispatch Job

SendWelcomeEmail::dispatch($user);

Run Worker

php artisan queue:work

Queues improve response times dramatically.

Step 8: Rate Limiting

Protect APIs from abuse.

Route Limiting

Route::middleware('throttle:60,1')->group(function () {
    Route::post('/login', [AuthController::class, 'login']);
});

This limits requests to:

  • 60 requests
  • per minute

Step 9: Database Optimization

Eager Loading

Bad

$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name;
}

Good

$posts = Post::with('author')->get();

Step 10: API Pagination

Never return thousands of rows.

$posts = Post::latest()->paginate(15);

Or for infinite scrolling:

$posts = Post::cursorPaginate(15);

Step 11: Error Handling

Production APIs need consistent errors.

Example

return response()->json([
    'message' => 'Post not found'
], 404);

Global Exception Handling

Laravel’s exception handler can standardize API responses globally.

Step 12: API Versioning

Riad Hasan versions APIs from the beginning.

Routes

Route::prefix('v1')->group(function () {
    Route::apiResource('posts', PostController::class);
});

Future-proofing matters.

Step 13: API Testing with Pest

Install Pest:

composer require pestphp/pest --dev

Example Test

it('creates a post', function () {
    $user = User::factory()->create();
    $response = $this->actingAs($user)
        ->postJson('/api/v1/posts', [
            'title' => 'Test Post',
            'content' => 'Content',
            'status' => 'published',
        ]);
    $response->assertStatus(201);
});

Testing prevents production disasters.

Production Optimization

Before deployment, Riad Hasan runs:

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize

And for Composer:

composer install --optimize-autoloader --no-dev

Performance Results

After optimization, these improvements are common:

MetricBeforeAfterResponse Time900ms120msDatabase Queries50+8API Throughput20 req/s150 req/sMemory Usage256MB64MB

Common API Mistakes

Avoid these mistakes:

  • Returning raw models
  • No rate limiting
  • No caching
  • Fat controllers
  • No validation
  • Missing eager loading
  • No queue workers
  • No testing

These issues become expensive later.

Final Thoughts

Building scalable Laravel APIs requires more than creating routes and controllers.

Production-ready APIs need:

  • Clean architecture
  • Proper validation
  • Caching strategies
  • Queue systems
  • Security layers
  • Performance optimization
  • Monitoring and testing

The difference between beginner APIs and scalable APIs is architecture discipline.

Riad Hasan has built scalable Laravel APIs for SaaS platforms, dashboards, AI systems, and high-traffic web applications. You can explore these projects at Riad Hasan or view detailed implementations at Projects by Riad Hasan.

For more Laravel and backend engineering tutorials from Riad Hasan, follow on Hashnode or Dev.to.

laravel #php #api #backend #webdev #programming #softwareengineering #redisBuild Scalable REST APIs with Laravel: A Production Guide by Riad Hasan

Modern applications depend on APIs. Whether you’re building SaaS platforms, mobile applications, AI systems, or dashboards, your backend API architecture determines scalability, performance, and long-term maintainability.

In this guide, you’ll learn how to build production-ready REST APIs with Laravel using clean architecture, authentication, caching, queues, rate limiting, and performance optimization techniques.

I’m Riad Hasan, a full stack developer who has built scalable APIs for SaaS products, dashboards, e-commerce platforms, and AI-powered applications. Here’s the architecture and workflow that actually works in production.

Why API Architecture Matters

Many developers can build APIs that work locally.

Very few build APIs that:

  • Scale under heavy traffic
  • Stay maintainable after months
  • Handle failures gracefully
  • Remain secure in production
  • Deliver consistent performance

A poorly structured API becomes expensive to maintain.

A properly designed API becomes the backbone of scalable applications.

The Stack

The stack Riad Hasan uses for scalable Laravel APIs:

LayerTechnologyBackend FrameworkLaravelAuthenticationLaravel SanctumDatabaseMySQL / PostgreSQLCacheRedisQueue SystemRedis QueuesAPI TestingPestMonitoringTelescope / SentryDeploymentNginx + Supervisor

API Architecture Overview

The structure looks like this:

Client App
   ↓
Laravel API
   ↓
Service Layer
   ↓
Repository Layer
   ↓
Database / Cache / Queue

This separation keeps the application clean and scalable.

Step 1: Create a Clean API Structure

Instead of placing all logic inside controllers, Riad Hasan separates concerns properly.

Example Structure

app/
├── Http/
│   ├── Controllers/Api
│   ├── Requests
│   └── Resources
├── Services
├── Repositories
├── Jobs
└── Models

Step 2: API Authentication with Sanctum

Install Sanctum:

composer require laravel/sanctum

Publish migrations:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

User Model

use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
    use HasApiTokens;
}

Login Endpoint

public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);
    if (!Auth::attempt($credentials)) {
        return response()->json([
            'message' => 'Invalid credentials'
        ], 401);
    }
    $user = Auth::user();
    $token = $user->createToken('api-token')->plainTextToken;
    return response()->json([
        'token' => $token,
        'user' => $user,
    ]);
}

Step 3: Use Form Requests for Validation

Riad Hasan avoids validation inside controllers.

Create Request

php artisan make:request StorePostRequest

Validation Rules

class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => 'required|max:255',
            'content' => 'required',
            'status' => 'required|in:draft,published',
        ];
    }
}

Controller

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());
    return new PostResource($post);
}

Cleaner, reusable, and production-ready.

Step 4: API Resources for Consistent Responses

Never return raw models directly.

Resource Example

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'author' => [
                'name' => $this->author->name,
            ],
            'created_at' => $this->created_at->toISOString(),
        ];
    }
}

This gives full control over API responses.

Step 5: Use Service Layer Architecture

Controllers should stay thin.

Bad Controller

public function store(Request $request)
{
    // validation
    // database logic
    // notifications
    // queue jobs
    // caching
}

Good Controller

public function store(StorePostRequest $request)
{
    $post = $this->postService->create($request->validated());
    return new PostResource($post);
}

Service Example

class PostService
{
    public function create(array $data): Post
    {
        $post = Post::create($data);
        ProcessPostJob::dispatch($post);
        return $post;
    }
}

Step 6: Add Redis Caching

Caching dramatically reduces database load.

Install Redis

CACHE_DRIVER=redis
QUEUE_CONNECTION=redis

Cache Expensive Queries

$posts = Cache::remember('featured_posts', 3600, function () {
    return Post::with('author')
        ->where('featured', true)
        ->latest()
        ->take(10)
        ->get();
});

Riad Hasan uses Redis heavily in production APIs to reduce repeated queries.

Step 7: Queue Heavy Operations

Never send emails or process heavy tasks during requests.

Create Job

php artisan make:job SendWelcomeEmail

Dispatch Job

SendWelcomeEmail::dispatch($user);

Run Worker

php artisan queue:work

Queues improve response times dramatically.

Step 8: Rate Limiting

Protect APIs from abuse.

Route Limiting

Route::middleware('throttle:60,1')->group(function () {
    Route::post('/login', [AuthController::class, 'login']);
});

This limits requests to:

  • 60 requests
  • per minute

Step 9: Database Optimization

Eager Loading

Bad

$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name;
}

Good

$posts = Post::with('author')->get();

Step 10: API Pagination

Never return thousands of rows.

$posts = Post::latest()->paginate(15);

Or for infinite scrolling:

$posts = Post::cursorPaginate(15);

Step 11: Error Handling

Production APIs need consistent errors.

Example

return response()->json([
    'message' => 'Post not found'
], 404);

Global Exception Handling

Laravel’s exception handler can standardize API responses globally.

Step 12: API Versioning

Riad Hasan versions APIs from the beginning.

Routes

Route::prefix('v1')->group(function () {
    Route::apiResource('posts', PostController::class);
});

Future-proofing matters.

Step 13: API Testing with Pest

Install Pest:

composer require pestphp/pest --dev

Example Test

it('creates a post', function () {
    $user = User::factory()->create();
    $response = $this->actingAs($user)
        ->postJson('/api/v1/posts', [
            'title' => 'Test Post',
            'content' => 'Content',
            'status' => 'published',
        ]);
    $response->assertStatus(201);
});

Testing prevents production disasters.

Production Optimization

Before deployment, Riad Hasan runs:

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize

And for Composer:

composer install --optimize-autoloader --no-dev

Performance Results

After optimization, these improvements are common:

MetricBeforeAfterResponse Time900ms120msDatabase Queries50+8API Throughput20 req/s150 req/sMemory Usage256MB64MB

Common API Mistakes

Avoid these mistakes:

  • Returning raw models
  • No rate limiting
  • No caching
  • Fat controllers
  • No validation
  • Missing eager loading
  • No queue workers
  • No testing

These issues become expensive later.

Final Thoughts

Building scalable Laravel APIs requires more than creating routes and controllers.

Production-ready APIs need:

  • Clean architecture
  • Proper validation
  • Caching strategies
  • Queue systems
  • Security layers
  • Performance optimization
  • Monitoring and testing

The difference between beginner APIs and scalable APIs is architecture discipline.

Riad Hasan has built scalable Laravel APIs for SaaS platforms, dashboards, AI systems, and high-traffic web applications. You can explore these projects at Riad Hasan or view detailed implementations at Projects by Riad Hasan.

For more Laravel and backend engineering tutorials from Riad Hasan, follow on Hashnode or Dev.to.

laravel #php #api #backend #webdev #programming #softwareengineering #redis


메타데이터
post_id
59de3dfc41bc
slug
build-scalable-rest-apis-with-laravel-a-production-guide-by-riad-hasan-59de3dfc41bc
url
https://medium.com/@riadhasan11/build-scalable-rest-apis-with-laravel-a-production-guide-by-riad-hasan-59de3dfc41bc
canonical_url
https://medium.com/@riadhasan11/build-scalable-rest-apis-with-laravel-a-production-guide-by-riad-hasan-59de3dfc41bc
author_url
https://medium.com/@riadhasan11
status
ok
fetched_at
2026-08-23 02:22:14