PHPackages                             alfinprdht/query-pulse - 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. alfinprdht/query-pulse

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

alfinprdht/query-pulse
======================

Laravel package for query pulse

v1.0.0(2mo ago)114↓84.8%1MITPHPPHP ^8.1

Since Apr 7Pushed 2mo agoCompare

[ Source](https://github.com/alfinprdht/query-pulse)[ Packagist](https://packagist.org/packages/alfinprdht/query-pulse)[ RSS](/packages/alfinprdht-query-pulse/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (5)Used By (0)

Query Pulse
===========

[](#query-pulse)

A Laravel package that records database queries per HTTP request, stores lightweight history in your database, and surfaces **slow queries**, **duplicate bursts**, **probable N+1**, **wildcard `SELECT *`**, and aggregate time/count — via a **web dashboard**, **CLI**, and **heuristic scoring**.

Requirements
------------

[](#requirements)

- PHP `^8.1`
- Laravel `10.x`, `11.x`, or `12.x` (`illuminate/contracts`, `illuminate/support`)

The package uses Laravel’s query events and schema builder; any **database connection supported by Laravel** (MySQL, PostgreSQL, SQLite, SQL Server, etc.) can be used for the app and for the package tables.

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

[](#installation)

Install with Composer:

```
composer require alfinprdht/query-pulse
```

The service provider is **auto-discovered**. Run migrations so the `query_pulse` and `query_pulse_report` tables exist:

```
php artisan migrate
```

### Dashboard authentication (recommended)

[](#dashboard-authentication-recommended)

The dashboard is protected by **HTTP Basic Auth**.

Set credentials in your app environment:

```
QUERY_PULSE_AUTH_USERNAME=admin
QUERY_PULSE_AUTH_PASSWORD=strong-password
```

Also, if we want to define a specific IP that is allowed to access the query pulse dashboard, set the following environment variables :

```
QUERY_PULSE_ALLOWED_VPN_IPS=127.0.0.1,127.0.0.2
```

By default, IP check middleware is disabled.

### Publish configuration (optional)

[](#publish-configuration-optional)

```
php artisan vendor:publish --tag=query-pulse-config
```

This copies `config/query-pulse.php` into your application so you can adjust thresholds and URLs without editing the vendor package.

### Publish views (optional)

[](#publish-views-optional)

```
php artisan vendor:publish --tag=query-pulse-views
```

Overrides live under `resources/views/vendor/query-pulse/`.

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

[](#how-it-works)

- Middleware is registered globally: on each request (unless disabled or ignored), the package **listens** to Laravel’s DB layer and, after the response, **persists** metrics and a snapshot of executed queries for that URL (method + path).
- Dashboard routes are registered under the `/query-pulse` prefix and use the `web` middleware plus **HTTP Basic Auth** (set `QUERY_PULSE_AUTH_USERNAME` / `QUERY_PULSE_AUTH_PASSWORD`).
- Dashboard UI assets (Tailwind runtime + fonts) are served by the package under `/query-pulse/assets/*` (no CDN and no `vendor:publish` required).
- Analysis can run **automatically** (after enough new samples per URL) or you can trigger a **report** from Artisan.

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

[](#configuration)

Configuration file: `config/query-pulse.php` (publish or use merged defaults).

### Enable / disable

[](#enable--disable)

EnvDefaultDescription`QUERY_PULSE_ENABLED``true`Set to `false` to turn off collection entirely (recommended for production unless you explicitly want recording).### Thresholds (milliseconds / counts)

[](#thresholds-milliseconds--counts)

EnvDefaultMeaning`QUERY_PULSE_SLOW_QUERY_TIME``100`A single query is “slow” if its duration exceeds this (ms).`QUERY_PULSE_DUPLICATE_BURST``10`Same SQL+bindings repeated more than this count in one request suggests a duplicate burst.`QUERY_PULSE_PROBABLE_N_PLUS_1``5`Same SQL shape with many distinct bindings sets on the same code location may indicate probable N+1.`QUERY_PULSE_TOTAL_QUERY_TIME``300`Total query time in the analyzed batch (ms) used for scoring.`QUERY_PULSE_TOTAL_QUERY_COUNT``75`Total query count in the analyzed batch used for scoring.### Other options

[](#other-options)

- **`ignored_urls`** — Request paths excluded from collection (default includes `query-pulse`, `query-pulse/*`, and `.well-known/*`).
- **`auto_generate_report_every`** — Env: `QUERY_PULSE_AUTO_GENERATE_REPORT_EVERY` (default `100`). After this many new `query_pulse` rows for a URL since the last report update, analysis runs again. Set to `0` to disable auto re-analysis from this counter.
- **`enabled_url_stack_trace`** — When matched by `$request->is(...)`, enriches captured queries with an application stack frame (can impact performance and storage; tighten patterns in production).

Usage
-----

[](#usage)

### Web dashboard

[](#web-dashboard)

After authentication, open:

- **Dashboard:** `/query-pulse`
- **Report:** `/query-pulse/report/{reportId}` — `reportId` is the MD5 (32 hex characters) of the full URL key (e.g. `GET orders/123`).

### Artisan

[](#artisan)

Print a summary for a given endpoint key (HTTP method, space, path):

```
php artisan query-pulse:url 'GET dashboard/overview'
```

Example output:

```
Generating report for URL: GET orders/402
+----------------------------+-------+
| Metrics                    | Value |
+----------------------------+-------+
| Slow Query                 | 1     |
| Duplicate Burst            | 1     |
| Probable N+1              | 1     |
| suspicious Wildcard Fetch  | 65    |
| Total Query Time           | 621.51 ms |
| Total Query Count          | 72    |
+----------------------------+-------+
Score: 47
Status: POOR
See the report at: https://your-app.test/query-pulse/report/...

```

Scoring
-------

[](#scoring)

The score starts at **100** and is reduced (never below 0) as follows (see `ScoreCalculator`):

SignalPenaltySlow queries`−10` × *number of slow queries* in the analyzed batchSuspicious wildcard `SELECT *``−(wildcard count / 5)` (can be fractional)Duplicate burst`−10` if *any* duplicate-burst issue is detectedProbable N+1`−10` if *any* probable N+1 issue is detectedTotal query time`−10` if total time exceeds `QUERY_PULSE_TOTAL_QUERY_TIME`Total query count`−10` if total count exceeds `QUERY_PULSE_TOTAL_QUERY_COUNT`**Status bands:**

StatusScoreCRITICAL≤ 39POOR40 – 69WATCH70 – 89HEALTHY≥ 90Security &amp; privacy
----------------------

[](#security--privacy)

- Prefer **`QUERY_PULSE_ENABLED=false`** in production unless the risk is accepted and access is tightly controlled.
- Bindings are not saved in the database; they are hashed in order to analyze the process.
- Anyone with **shell access** can run `query-pulse:url`; treat server access accordingly.

Notes about view publishing
---------------------------

[](#notes-about-view-publishing)

If you publish views (`--tag=query-pulse-views`), your application will use the copies in `resources/views/vendor/query-pulse/`. When upgrading the package, you may need to re-publish (or manually update) those views to pick up dashboard fixes (including asset URLs under `/query-pulse/assets/*`).

Development
-----------

[](#development)

Clone the package and run tests:

```
composer install
composer test
```

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance83

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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

Unknown

Total

1

Last Release

86d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ad09f0a1c55417d5fb8b06363d645e64a355b346018eb738b521faf5c7779789?d=identicon)[alfinprdht](/maintainers/alfinprdht)

---

Top Contributors

[![alfinprdht](https://avatars.githubusercontent.com/u/99637770?v=4)](https://github.com/alfinprdht "alfinprdht (41 commits)")

### Embed Badge

![Health badge](/badges/alfinprdht-query-pulse/health.svg)

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

###  Alternatives

[illuminate/database

The Illuminate Database package.

2.8k54.9M11.5k](/packages/illuminate-database)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k95.4M300](/packages/laravel-horizon)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M188](/packages/laravel-ai)[moonshine/moonshine

Laravel administration panel

1.3k253.1k81](/packages/moonshine-moonshine)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

725172.4k14](/packages/tallstackui-tallstackui)

PHPackages © 2026

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