Back to blog
LaravelPHPBuenas prácticas

Run Large PlanetScale Queries in Laravel with OLAP

Laravel can isolate analytical Vitess queries without leaving reused database connections in the wrong workload mode.

By Isma4 min read

The issue is not only query duration

A full export, an aggregate report, or a backfill may need to read far more rows than a typical request. With a Vitess database such as PlanetScale, that work can be treated as analytical instead of regular OLTP traffic. The important detail is that this changes connection state, and a connection reused by a worker should not remain in a different mode after the task ends. Laravel provides an API that limits that change to the block of code that actually needs it. (laravel.com)

The documented API runs on a connection

It may be tempting to write DB::olap(), but the official documentation shows the API being called on a specific connection: DB::connection('mysql')->olap(...). The callback receives the connection that should run the query, and its return value becomes the return value of olap. That keeps the query next to the decision to run it as analytical work without manually changing state before and after it. It also avoids hiding an important operational choice in global configuration.

use Illuminate\Support\Facades\DB;
 
$totals = DB::connection('mysql')->olap(
    fn ($connection) => $connection->table('orders')
        ->selectRaw('customer_id, sum(total) as total')
        ->groupBy('customer_id')
        ->get()
);

This works well inside an Artisan command, a queued job, or an export process. The callback can build queries with Laravel's query builder just like the rest of the application. There is no need to change how results are collected or introduce a dedicated client for the report. Laravel returns whatever the callback returns. (laravel.com)

Why the callback matters for workers and Octane

Laravel sets the OLAP workload on both read and write connections before invoking the callback. When the callback finishes, it resets the workload to OLTP, including when an exception is thrown inside the block. That is useful when a process remains alive and may reuse connections for later work, which is common with queue workers and long-running servers. Cleanup belongs to the scope of the operation instead of relying on an extra call being remembered in every error path. (laravel.com)

I would not wrap every slow query in this method just for the sake of it. I would keep it for clearly analytical operations that are separate from a normal web request. The explicit boundary also makes it easier to review which queries receive this treatment and where they run. If I need query timing, SQL logging, or bindings, Laravel's usual observability tools can still be used around the operation.

The fine print

olap does not turn a poorly designed query into a cheap one, and it does not replace reviewing indexes, filters, aggregations, or data volume. It also does not split an export into chunks, resume a backfill, or store the resulting file. The process still needs sensible limits, memory control, and a recovery plan for failures. Its specific benefit is that it safely scopes Vitess workload changes to one operation.

The documentation also states that, for a MySQL connection not using Vitess, the callback runs without changing the workload. If I need to check that explicitly, I can call isVitess() on the connection before choosing a PlanetScale-specific path. This makes it possible to share code across environments without assuming every MySQL connection behaves the same way. Business logic should not depend on OLAP when the functional result must remain identical across database engines. (laravel.com)

$isVitess = DB::connection('mysql')->isVitess();
 
if ($isVitess) {
    // Apply Vitess-specific operational decisions.
}

A small addition with a clear boundary

The value of this API is that it expresses operational intent without scattering connection details throughout the codebase. The query remains standard Laravel code; only its execution context is exceptional. For large PlanetScale jobs, I prefer that explicit boundary over changing the workload manually and trusting every return path and exception handler to reset it. It solves one focused problem rather than providing an excuse to send every expensive query to production.


Source: Laravel News. Official documentation: Laravel Database — Running Analytical Queries on Vitess.

Newsletter

What I learn coding with AI, every two weeks in your inbox.

Real numbers, mistakes included. No spam, unsubscribe in one click.

No spam, unsubscribe in one click. I only use your email to send you this and the newsletter. More in the privacy policy.