PHPackages                             juanparati/query-timeout - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. juanparati/query-timeout

ActiveLibrary[Database &amp; ORM](/categories/database)

juanparati/query-timeout
========================

Set a timeout to your Laravel queries.

13.3(3d ago)02↓100%MITPHPPHP &gt;=8.2CI passing

Since Mar 19Pushed 3d agoCompare

[ Source](https://github.com/juanparati/query-timeout)[ Packagist](https://packagist.org/packages/juanparati/query-timeout)[ RSS](/packages/juanparati-query-timeout/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (4)Versions (4)Used By (0)

[![test](https://github.com/juanparati/laravel-timeout/actions/workflows/on_push.yml/badge.svg)](https://github.com/juanparati/laravel-timeout/actions/workflows/on_push.yml/badge.svg)

Query Timeout ⏰
===============

[](#query-timeout-)

A Laravel database library that implements query timeouts at the database level, helping you implement the [circuit breaker pattern](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern).

Compatible with the following RDBMS:

- MariaDB
- MySQL
- PostgreSQL

Installation
------------

[](#installation)

```
composer require juanparati/query-timeout
```

How it works.
-------------

[](#how-it-works)

### Running queries

[](#running-queries)

Use the `QueryTimeout` facade to set a maximum execution time for your queries:

```
\QueryTimeout::run(
    fn() => \DB::select('SELECT SLEEP(4)'),     // Your query comes here (Use pg_sleep for testing with PostgreSQL)
    3                                     ,     // Interrupt if a query takes more than 3 seconds (Keep null for default timeout)
    'myconnection'                              // Database connection (Keep null for the default connection)
    fn() => logs()->error('Timeout here')       // Run this callback before throwing QueryTimeoutException
);
```

or using the fluent builder:

```
\QueryTimeout::build()
    ->for(fn() => \DB::select('SELECT SLEEP(4)'))
    ->timeout(3)
    ->on('myconnection')
    ->whenTimeout(fn() => logs()->error('Timeout here'))
    ->run();
```

In the previous example if the query exceeds the specified timeout (3 seconds), it will send an error to the log and throw a `\Juanparati\QueryTimeout\QueryTimeoutException`.

### Returning direct results

[](#returning-direct-results)

Instead of passing the results as reference like in the following example:

```
$users = null;

\QueryTimeout::run(
    function() use (&$users) => $users = User::where('name', 'like', 'john%')->get()
);
```

you can also get the results directly:

```
$users = \QueryTimeout::run(
    fn() => User::where('name', 'like', 'john%')->get()
)->getResult();
```

### Obtain execution time

[](#obtain-execution-time)

RDBMS are not very accurate stopping queries, but you can get the real execution time of the query using the `getQueryTime` method:

```
$queryTime = \QueryTimeout::run(
    fn() => \DB::select('SELECT SLEEP(4)')
)->getQueryTime();
```

The configuration key ´resolution´ defines the precision of the time measurement output.

How it works under the hood
---------------------------

[](#how-it-works-under-the-hood)

Instead of using co-routines or parallel execution monitoring, this library leverages native database features:

- MariaDB: [max\_statement\_time](https://mariadb.com/docs/server/ha-and-performance/optimization-and-tuning/system-variables/server-system-variables#max_statement_time)
- MySQL: [max\_execution\_time](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html#optimizer-hints-execution-time)
- PostgreSQL: [statement\_timeout](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT)

The timeout mechanism works by:

1. Setting the timeout value for the database session.
2. Executing the query.
3. Restoring the original timeout value even if the main query fails.

```
╔════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Example flow for MariaDB                                                                           ║
║                                                                                                    ║
║     ┌─────────────────────────────────────────┐                                                    ║
║   1.│SET @@SESSION.max_statement_time=3;      │ ◀─── Set the desired maximum time for the session  ║
║     └─────────────────────────────────────────┘                                                    ║
║     ┌─────────────────────────────────────────┐                                                    ║
║   2.│SELECT * FROM USERS;                     │ ◀─── Execute the query                             ║
║     └─────────────────────────────────────────┘                                                    ║
║     ┌─────────────────────────────────────────┐                                                    ║
║   3.│SET @@SESSION.max_statement_time=0;      │ ◀─── Restore the original session maximum time     ║
║     └─────────────────────────────────────────┘                                                    ║
╚════════════════════════════════════════════════════════════════════════════════════════════════════╝

```

### Limitations

[](#limitations)

### MySQL-specific

[](#mysql-specific)

- Only "select" queries are timed out in MySQL.
- Unfortunately, for pure computational queries MySQL kills the query silently without raising any error, so in this case this library determines when a query is timed out measuring the execution time and creating artificially an exception. This method may not be very accurate (See the configuration `mysql.recheck_timeout` for changing this behavior).

### MariaDB-specific

[](#mariadb-specific)

- Old MariaDB embedded servers may not work properly.
- COMMIT statements don't timeout in Galera clusters.

### General Limitations:

[](#general-limitations)

- May be unreliable with persistent connections or connection pools in distributed environments

Best Practices
--------------

[](#best-practices)

1. Keep application logic outside the closure.

✅ Recommended:

```
$users = null;

\QueryTimeout::run(
    function() use (&$users) => $users = User::where('name', 'like', 'john%')->get(),
);

foreach ($users as $user) {
    if ($user->password_expiration > now()) {
        ... // Your application logic
    }
}
```

❌ Not recommended:

```
\QueryTimeout::run(
    function() {
        $users = User::where('name', 'like', 'john%')->get()

        foreach ($users as $user) {
            if ($user->password_expiration > now()) {
                ... // Your application logic
            }
        }
    }
);
```

2. In MySQL, try to use only one query per closure (Be cautious with ORM operations that might trigger multiple queries).

Configuration
-------------

[](#configuration)

### Publish configuration (Optional)

[](#publish-configuration-optional)

```
artisan vendor:publish --tag="query-timeout"
```

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance99

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

3d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4caf72b4d969cfb8cdfbdc1d594c85b51c9316caf76b80aa0f9de7e3736cf59f?d=identicon)[juanparati](/maintainers/juanparati)

---

Tags

laraveldatabaseormquerydbtimeoutcircuit breaker

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/juanparati-query-timeout/health.svg)

```
[![Health](https://phpackages.com/badges/juanparati-query-timeout/health.svg)](https://phpackages.com/packages/juanparati-query-timeout)
```

###  Alternatives

[illuminate/database

The Illuminate Database package.

2.8k51.5M8.2k](/packages/illuminate-database)[illuminated/db-profiler

Database Profiler for Laravel Web and Console Applications.

169234.1k](/packages/illuminated-db-profiler)[tpetry/laravel-query-expressions

Database-independent Query Expressions as a replacement to DB::raw calls

356388.9k1](/packages/tpetry-laravel-query-expressions)[cybercog/laravel-clickhouse

ClickHouse migrations for Laravel

159150.0k](/packages/cybercog-laravel-clickhouse)[laravel-doctrine/acl

ACL for Laravel and Doctrine

45435.5k7](/packages/laravel-doctrine-acl)[webparking/laravel-db-rebuild

A laravel package that allows for quick database rebuilds with presets.

448.8k](/packages/webparking-laravel-db-rebuild)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
