mongo-query-profiler
v1.0.9
Published
A command-line utility for MongoDB that activates the database profiler, generates interactive html report to let you identify performance bottlenecks
Maintainers
Readme
I’m currently looking for a new role in backend and front-end engineering. Node.js, MongoDB, Vue, etc. Open to remote full-time or long-term contract work — including compensation in crypto. Feel free to reach out.
CV: https://drive.google.com/file/d/1afd9T1rpAua0hPcRQUeg0QG4BSLqqjPX/view?usp=sharing LinkedIn: https://www.linkedin.com/in/dmitry-eroshenko Telegram: @airs0urce Email: [email protected]
Mongo Query Profiler
Command‑line helper that collects slow query samples and converts them into an interactive HTML report so you can spot bottlenecks quickly.
This is an simple tool which doesn't require any initial setup, for long-term usage you can consider Percona Monitoring And Management for MongoDB: https://www.percona.com/software/database-tools/percona-monitoring-and-management/mongodb-monitoring
Motivation
I built this profiler when I had to analyze a MongoDB instance that hosted many databases, and doing it manually through the built-in profiler felt painfully slow. After seeing how Studio 3T approaches query profiling (https://studio3t.com/knowledge-base/articles/mongodb-query-performance/), I wanted something with the same usability but without two major drawbacks:
- Studio 3T cannot profile every database in the same instance in parallel.
- Studio 3T Query Profiler is locked behind a paid license that costs $499 per year.
This project aims to beat those limitations by offering a profiler that keeps the good parts (simple reports, actionable insights), works across multiple databases simultaneously, and remains completely free and open for anyone to use.
Contents
- Motivation
- Profiler Report Screenshot
- Quick Start
- Typical workflow
- CLI Commands & Examples
- Optimization Reading List
- Connecting Through an SSH Tunnel
- Best Practices
- Troubleshooting
Profiler Report Screenshot
Quick Start
Install from NPM
- Install Node.js: https://nodejs.org/
- Install package globally
npm install -g mongo-query-profiler - Run commands
mongo-query-profiler --help
Run using NPX
- Install Node.js: https://nodejs.org/
- Run using npx:
npx mongo-query-profiler --help
Run from cloned source code
- Install Node.js: https://nodejs.org/
- Clone repo:
git clone https://github.com/airs0urce/mongo-query-profiler.git && cd mongo-query-profiler - Install dependencies:
npm install - Install package globally:
npm install -g - Run commands:
mongo-query-profiler --help
Typical workflow
Note: If your MongoDB instance is behind a firewall or not exposed on a public port, see Connecting Through an SSH Tunnel
- Collect profiling data from your MongoDB instance
mongo-query-profiler collect mongodb://127.0.0.1:27017 - Generate HTML report:
mongo-query-profiler report ./report.html - Open "report.html"
CLI Commands & Examples
Every command supports -h, --help for details.
Examples: mongo-query-profiler --help mongo-query-profiler collect --help mongo-query-profiler report --help mongo-query-profiler cleanup-mongodb --help mongo-query-profiler cleanup-reports --help
collect [options] <connection url> — capture slow queries
Enable the profiler on one or more databases, wait for the sampling window to finish, then dump each database’s system.profile collection as JSON.
Syntax example:
mongo-query-profiler collect mongodb://user:pass@host:27017 \
--slowms 50 \
--databases sales analytics \
--databases-parallel 1 \
--duration 5 \
--max-profile-size 8Where "mongodb://user:pass@host:27017" is MongoDB connection string. If you don't have user/password "mongodb://host:27017".
This command will profile "sales" and "analytics" databases for 5 minutes. Profiles will be saved in profiling-reports/REPORT_<timestamp>/.
Options
--slowms <ms>
Specify the minimum query execution time (in milliseconds) to be included in the profiling output. Default: 100 ms
--databases <databases...>
List the target databases to profile. If omitted, profiling runs on all databases available on the connected MongoDB instance. Default: “all”
--databases-parallel <number>
Controls how many databases have profiling enabled at the same time. This helps reduce overhead on production systems, as MongoDB’s profiler adds measurable load when active. Use 0 to enable profiling on all databases simultaneously. Default: 0
--duration <minutes>
Time window (in minutes) during which profiling remains active. Default: 1
--max-profile-size
Maximum allowed size of the system.profile collection, expressed in megabytes. Default: 2 MB
-h, --help
report <output-html-file> — build the HTML dashboard
Converts the latest raw profiles into a single HTML file.
Syntax example:
mongo-query-profiler report ./report.htmlThe command gathers profiles from profiling-reports folder and embeds them into one HTML file,
so you get single self-contained interactive report, analyze it and send to other people by email/messenger etc.
cleanup-mongodb <connection url> — disable profiler and deletes profiles in each database
Stops the profiler on all databases reachable through the provided URI and drops system.profile collections. Handy if collect was interrupted.
Syntax example:
mongo-query-profiler cleanup-mongodb mongodb://user:pass@host:27017cleanup-reports — delete local artifacts
Removes every subfolder inside profiling-reports/, freeing disk space or prepping for a fresh capture.
Syntax example:
mongo-query-profiler cleanup-reportsWhen You Find a Slow Query
- Insert query in MongoDB Compass to "find" filter make sure you added all parts of query like "projection", "limit", "sort".
- Click Explain in Compass to inspect the winning plan, stage latencies, and server stats.
- Compare the
executionStatsresults with the profiler sample to confirm the same pattern (blocked on IXSCAN vs COLLSCAN, highkeysExamined, highdocsExamined, etc.).
Optimization Reading List
- Single Field Indexes: https://www.mongodb.com/docs/manual/core/indexes/index-types/index-single/
- Compound indexes: https://www.mongodb.com/docs/manual/core/index-compound/
- The ESR Guideline. Important to be able to make optimal compound index: https://www.mongodb.com/docs/manual/tutorial/equality-sort-range-guideline/
- Comparing
keysExamined(index reads) vsdocsExamined(slow disk reads): https://www.mongodb.com/docs/manual/tutorial/explain-slow-queries/#evaluate-key-examination. - Use covered query to mitigate slow disk reads and get data from memory only: https://www.mongodb.com/docs/manual/core/query-optimization/#covered-query
- Whenever possible rewrite your query to use positive filters. Instead of using
$neor$nin - How to optimize slow query with
{field: {$exists: true/false}}filter: https://www.mongodb.com/docs/manual/reference/operator/query/exists/#use-a-sparse-index-to-improve--exists-performance, example: https://www.mongodb.com/community/forums/t/exists-query-with-index-very-slow/4960/6 - When you add an index, check if you can use Partial Index which decreases memory usage and speeds up index scans: https://www.mongodb.com/docs/manual/core/index-partial/
Connecting Through an SSH Tunnel
If your MongoDB server is only reachable inside a private network, create an SSH tunnel and point the profiler to the local forwarded port.
Terminal example
ssh -N -L 27018:127.0.0.1:27017 [email protected]-L 27018:127.0.0.1:27017forwards local port27018to the remote MongoDB running on the bastion’s127.0.0.1:27017-Nkeeps the tunnel open without running a remote shell
Then run mongo-query-profiler collect mongodb://localhost:27018.
GUI helpers
- macOS: Core Tunnel simplifies saved tunnels and auto-reconnects
- Windows: PuTTY or MobaXterm both support local port forwarding profiles
Whichever client you use, ensure the tunnel stays open for the entire profiling window defined by --duration.
Best Practices
- Turn on profiling in production sparingly; use
--databases-parallelto limit concurrent load. - Keep
--durationas short as possible while still capturing representative load spikes. - After tuning queries/indexes, use Compass Explain to confirm changes helped.
Troubleshooting
- In MongoDB sharded clusters, connect directly to the shards rather than the mongos router, since profiler data on mongos will not provide useful information.
- If your reports are empty, increase the --duration or lower the --slowms value so the profiler can capture enough events.
