Skip to main content
Yosavo Studio by Youssef Ibaichou , home
Expertise

Laravel

Laravel has been a core part of my backend work across business applications, SaaS products, custom platforms and API-driven systems. I use it as a practical framework for building maintainable backend systems rather than treating framework conventions as architecture by themselves.

Application structure · Eloquent · Queues · Testing

How I think about it

How I think about Laravel

I prefer simple Laravel conventions until application complexity gives us a reason to introduce additional architectural layers. The goal is maintainability, not abstraction for its own sake.

  • Framework conventions first; new layers only when they remove real duplication or complexity.
  • Controllers coordinate. They don't decide business rules.
  • The database is part of the design — relationships, indexes and transactions are not afterthoughts.
  • Anything slow or external goes on a queue, and every job is safe to run twice.

Key experience

Where this comes from

  • Lead developer on a multi-tenant collaboration platform built with Laravel, Vue.js, MySQL and AWS — architecture, database design, APIs and frontend integration.
  • Laravel is the backend of Yotria, the portfolio SaaS I'm building as founder.
  • Web applications, internal business systems and integrations built with Laravel since my early full-stack work.

Scope

What I know

  • Application structure
  • Controllers & form requests
  • Service / action classes
  • Eloquent & relationships
  • Migrations & indexing
  • REST APIs & resources
  • Policies & gates
  • Queues & jobs
  • Events & listeners
  • Filesystem & S3
  • Feature & unit testing
  • Deployment & operations

Deep dive

Laravel in practice

On this page (13 topics)

Application structure

Laravel gives each responsibility an obvious home. Most maintainability problems I see come from ignoring those homes: business rules in Blade templates, authorization inside controllers, HTTP calls inside models.

Where responsibilities live in a Laravel application
app/
├─ Http/Controllers/    coordinate the request
├─ Http/Requests/       validate input
├─ Models/              data and relationships
├─ Policies/            who can do what
├─ Services/            multi-step workflows (only when needed)
├─ Jobs/                slow or external work
├─ Events/, Listeners/  side effects after something happened
└─ Console/Commands/    maintenance and scheduled tasks

Controllers

A good controller reads like a summary: authorize, validate through a form request, call the thing that does the work, return a response or resource. When a controller method passes forty lines, it's usually hiding a workflow that deserves a name.

A thin controller action
public function store(StoreInvitationRequest $request, Organization $organization)
{
    $this->authorize('invite', $organization);

    $invitation = $this->invitations->send(
        $organization,
        $request->validated('email'),
        $request->validated('role'),
    );

    return new InvitationResource($invitation);
}

When a service layer helps

I don't add a service layer by default. For CRUD-heavy features, models, form requests and policies are enough, and wrapping them in services adds indirection without value.

A service or action class earns its place when a workflow spans several models, must run in a transaction, talks to an external system, or is triggered from more than one entry point — a controller, a queued job and a console command. Then giving it one home makes it testable and keeps the rules consistent.

Eloquent & database design

Eloquent is productive until it hides the cost of a query. The classic issue is N+1: a list that lazily loads a relationship for every row. I eager load deliberately, use withCount and aggregates instead of loading collections just to count them, and turn on lazy-loading prevention in development so the problem shows up before production does.

Migrations are part of the design: foreign keys, indexes on the columns used for filtering and tenant scoping, and transactions around multi-step writes. When a query matters, I read the SQL and the query plan instead of trusting the ORM.

Eager loading and counts without N+1 queries
// A fixed number of queries, however many projects are on the page.
$projects = Project::query()
    ->whereBelongsTo($organization)
    ->with('owner:id,name')
    ->withCount('files')
    ->latest()
    ->paginate(25);

APIs

API resources keep the response shape separate from the database schema, so renaming a column doesn't break clients. Validation lives in form requests, collections are paginated by default, and errors come back in one consistent format with meaningful status codes.

Authentication depends on the client — session-based for a first-party SPA, tokens for third-party or mobile clients — and authorization still runs on every endpoint.

Related: API Development expertise

Authorization

Policies are where access rules belong: one class per resource, called from controllers, jobs and API endpoints alike. In a multi-tenant application the first check is always “does this resource belong to the current tenant?”, then “does this member's role allow the action?”. Gates cover organization-wide permissions that aren't tied to a single model.

Queues & jobs

Emails, exports, file processing and calls to external APIs run in jobs. The details that matter in production: timeouts and retry counts chosen per job, backoff for rate-limited providers, a failed handler that leaves a trace, and idempotency — a job that might run twice must not charge twice or send two emails.

Jobs receive identifiers rather than large serialized models, and re-check state when they run, because the world may have changed since they were dispatched.

Events

Events are useful when one action has several independent consequences — an accepted invitation might notify the inviter, write an audit entry and sync a CRM. They're harmful when they hide the main flow: if a step is essential to the operation, it should be a visible call, not a listener someone has to discover.

File handling

The filesystem abstraction lets the same code write to local disk in development and S3 in production. Files are private by default and served through short-lived temporary URLs after an authorization check; storage paths include the tenant; and heavy exports are generated in queued jobs that notify the user when they're ready.

Related: AWS expertise

SaaS patterns

Laravel makes the common SaaS building blocks straightforward, but the design choices are still yours: global scopes or explicit scoping for tenant data, middleware that resolves the current organization, policies aware of membership roles, one entitlement check for plan features and usage limits, and webhook-driven subscription state.

Related: SaaS Development expertise

Integrations

Each third-party integration gets its own client class with timeouts, retries and error mapping, configured per environment. Inbound webhooks are verified, logged and handed to a job, so the provider gets a fast response and processing can be retried safely.

Testing

Feature tests that exercise HTTP endpoints and jobs give the most confidence per line: they cover validation, authorization, the database and the response together. Unit tests are for logic with real branching — pricing rules, entitlement calculations, date handling.

I avoid tests that only restate the framework, such as asserting that a relationship method returns a relationship. Valuable tests assert business outcomes — and especially the actions that must be denied.

Production

A Laravel application in production is more than the web server: supervised queue workers, the scheduler running, config and routes cached at deploy time, logs going somewhere searchable, and deployments that run migrations safely and restart workers so they pick up new code.

In practice

Common problems I work with

  • Fat controllers mixing validation, business rules and HTTP calls
  • N+1 queries and slow list pages
  • Authorization logic duplicated across controllers and views
  • Jobs that fail silently or aren't safe to retry
  • Tests that pass but don't protect business rules
  • Tenant scoping that depends on developers remembering a where clause

Real products

How it connects to real products

Laravel has been the backend for business applications, SaaS products and API-driven systems I've built and led.

  • Enterprise SaaS

    Multi-Tenant Collaboration Platform

    Lead developer on a Laravel, Vue.js, MySQL and AWS platform — multi-tenant architecture, database design and REST APIs.

    Private client project
  • SaaS / Portfolio Builder

    Yotria

    Portfolio SaaS built as founder: a Laravel backend serving a React frontend, alongside a Python microservice.

    Coming soon
  • School Management SaaS / EdTech

    Yo Madrassa

    School management SaaS built with Laravel, where role-based access, payments and day-to-day administration are core backend concerns.

See all selected work

Related expertise

Vue.js

Vue product interfaces: component boundaries, composables, state and Laravel integration.

  • Composition API
  • State ownership
  • Laravel + Vue
  • Accessibility

API Development

Predictable API contracts: validation, errors, authorization, idempotency and webhooks.

  • API design
  • Error handling
  • Idempotency
  • Webhooks

Multi-Tenant SaaS

Tenant boundaries enforced everywhere: data, jobs, files, caches and reports.

  • Data isolation
  • Tenant context
  • Membership
  • Noisy neighbours

SaaS Development

Tenancy, permissions, plans, billing and the realities of running SaaS in production.

  • Multi-tenancy
  • Permissions
  • Billing
  • Production delivery

Related services

  • Custom Software Development

    Build reliable web platforms, SaaS products, dashboards, APIs, and internal tools with modern full-stack technologies.

    Learn more
  • SaaS Product Development

    Design and build SaaS products from MVP to production, including architecture, user management, subscriptions, integrations and cloud infrastructure.

    Learn more
Let's talk

Have a technical challenge?

Whether it's an architecture decision, a delivery problem or something specific to Laravel, I can help you find a practical path forward.

What happens next

  1. Share your goal

    A few lines about the product, problem, or audit need.

  2. Get a quick read

    A practical reply on the best technical path forward.

  3. Move forward

    A clear scope, estimate, or concrete next step.