aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Development

Eloquent vs Query Builder: When to Use Which

When you set up the data layer in Laravel, the first big decision you face is between the Eloquent ORM and the query builder; the eloquent query builder pairing actually rests on the same foundation but works at different levels of abstraction. Eloquent maps tables to model objects and brings relationships, events and mutators along with it. The query builder, on the other hand, stays much closer to SQL through a fluent interface. There is no single answer to which one is "right": the right answer depends on what the job in front of you actually is.

They share the same core

An important point: Eloquent is built on top of the query builder. When you call where() on a model, you are in fact reaching a query builder instance behind the scenes. So Eloquent is not a "slow alternative" — it is a higher level that adds an object layer, relationship management and model events on top of the query builder. The performance difference comes not from the engine itself but from the work that extra layer does: turning every row into a PHP object (hydration) and managing relationships has a cost.

When Eloquent shines

Eloquent stands out clearly in CRUD scenarios where business logic is central and you read and write a small-to-moderate number of records. Readability and maintainability are the real wins here:

  • Relationships: you reach related data in a single line like $user->posts; with with() you do eager loading and solve the N+1 query problem.
  • Model events: events like creating and saved, observers, and mutators/casts run automatically.
  • Soft deletes, timestamps, scopes: most repeated logic is gathered in one place through traits and scopes.
// Prevent N+1 with eager loading
$posts = Post::with('author', 'comments')
    ->where('published', true)
    ->latest()
    ->get();

foreach ($posts as $post) {
    echo $post->author->name; // no extra query
}

When the query builder is better

The query builder comes into play when you don't need model behaviour and performance is critical. Reports over thousands of rows, bulk updates, complex join and aggregate queries are exactly its domain. Because it doesn't turn every row into a model object, it is lighter on memory and CPU.

// A direct, lightweight reporting query
$stats = DB::table('orders')
    ->select('user_id', DB::raw('SUM(total) as total'))
    ->where('created_at', '>=', now()->subMonth())
    ->groupBy('user_id')
    ->having('total', '>', 1000)
    ->get();

Here you don't want a model object, relationship or event anyway; you just want to add up the numbers and return them. The query builder does this without hydration overhead and returns stdClass objects.

Think about the performance trade-off in numbers

In practice the difference is rarely felt when fetching a single record; it's all about scale. There is no measurable gap between pulling 50 rows with Eloquent versus the query builder. But if you're looping over 50,000 rows for an export job, creating a model for every row consumes serious memory. A few practical rules:

  • Large reads + processing: stream rows with the query builder or Eloquent's cursor()/lazy() methods instead of loading them all into memory.
  • Bulk updates: Model::where(...)->update([...]) runs as a single query but does not fire model events; use it knowing that.
  • If you only need a few columns: limit columns with select() even in Eloquent; pulling unnecessary data slows hydration down.
// Process 50,000 rows without piling them into memory
Order::where('exported', false)
    ->lazy()
    ->each(function ($order) {
        // one model at a time, low memory
    });

Using both together is the most realistic path

Instead of a right/wrong dilemma, most projects use both. Writing CRUD and form handling with Eloquent while leaving heavy dashboard queries to the query builder, in the same application, is perfectly normal. You can even drop down to raw SQL where needed inside Eloquent with whereRaw() or selectRaw(), tuning performance while keeping the model advantages. When you drop to raw queries, don't neglect parameter binding; usage like whereRaw('price > ?', [$min]) protects you against SQL injection.

Questions to ask when deciding

  • Are relationships, events or casts needed for this job? If so, Eloquent.
  • How many rows will come back, and will I turn them all into objects? If many, query builder or lazy().
  • Is this a hot path (does it run on every request)? If hot, measure and simplify if needed.
  • Is readability or a millisecond more valuable? For most screens, readability wins.

Frequently Asked Questions

Is Eloquent really slower than the query builder?

It's not the engine on its own — turning every row into a PHP object (hydration) and managing relationships is what slows it down. With few records the difference is imperceptible; over thousands of rows the query builder is noticeably lighter.

Can I use raw SQL inside Eloquent?

Yes. You can add raw fragments with whereRaw(), selectRaw() and DB::raw(). Always pass values via parameter binding rather than concatenating strings directly.

Which should be my default choice?

Start with Eloquent; the code stays cleaner and easier to maintain. Once you profile and find a bottleneck, move that specific query to the query builder or a streaming method.

Is your Laravel app's data layer slow, or are you just unsure where to start? I can help you build a scalable architecture that uses Eloquent and the query builder in the right places. Get in touch to talk about your project.

Bu kategorideki tüm yazılar →

Devamı için