Performance and Operational Controls
Configure AQL result set limits, query timeouts, and rate limiting for JFrog Artifactory. Includes optimization best practices for indexing, pagination, and efficient queries.
This page covers result set limits, rate limiting configuration, and best practices for writing performant AQL queries.
What Are the AQL Result Set Limits?
The maximum number of AQL search results is limited as follows:
- For Artifactory SaaS platforms starting from version 7.100.2, a fixed value of 500,000 is set as the default maximal result set size to limit the search/AQL API call response. When this limit is reached, no further results are displayed and the user receives the following message: "AQL query reached the search hard limit, results are trimmed."
- For Artifactory SaaS version 7.107.0 and above,
**aql.search.query.max.limit**is set to 500,000 results. This limit optimizes search result integrity and protects database performance. - For Artifactory self-managed, there is no default maximum result limit. However, from self-managed version 7.90.6 and later users can limit search results with the system property
**aql.search.query.max.limit**. - AQL queries also have a maximum query string length of 6,000 characters by default (configurable via the system property
**aql.search.query.size.limit**). Queries exceeding this limit receive an HTTP 400 (Bad Request) response.
How Do I Configure AQL Rate Limiting?
From Artifactory version 7.84, self-managed instances limit the number of search/AQL requests that can run in parallel. This protects the instance from overload when many concurrent AQL queries are executed. When the limit is reached, additional requests receive an HTTP 429 (Too Many Requests) response until capacity becomes available.
Configuration Properties
Configure AQL query rate limiting using the following properties in the$JFROG_HOME/artifactory/var/etc/artifactory/artifactory.system.properties file. Restart Artifactory after making changes.
| Property | Description | Default |
|---|---|---|
artifactory.aql.queries.limit.enabled | Enable or disable AQL query rate limiting. Set tofalse to disable throttling. | true(7.84.x);false(7.84.16 and later) |
artifactory.aql.queries.unlimited.agents | Comma-separated list of user agents that are not limited. | pipeline, xray, artifactory, distribution, federation |
artifactory.aql.queries.limit | Maximum number of AQL/search API calls that can run in parallel. | 3 |
artifactory.aql.queries.pending.timeout.millis | When the limit is reached, how long (in milliseconds) a request waits before receiving a 429 response. | 10000 |
Disabling Rate Limiting
If you experience unexpected 429 errors and need to disable rate limiting, add the following line toartifactory.system.properties:
artifactory.aql.queries.limit.enabled=falseTuning Rate Limiting
To allow more concurrent AQL queries, increaseartifactory.aql.queries.limit. To exempt additional clients (for example, CI agents), add their user agent toartifactory.aql.queries.unlimited.agents.
What Are the Query Timeout Defaults?
AQL queries are subject to timeout limits to protect database resources. If a query exceeds its timeout, the database cancels it and Artifactory returns an HTTP 408 (Request Timeout) response.
Configure query timeouts using the following properties in$JFROG_HOME/artifactory/var/etc/artifactory/artifactory.system.properties. Restart Artifactory after making changes.
| Property | Description | Default |
|---|---|---|
artifactory.aql.query.timeout.seconds | Maximum execution time (in seconds) for AQL queries from the REST API. | 900 (15 minutes) |
artifactory.aql.query.timeout.for.ui.seconds | Maximum execution time (in seconds) for AQL queries triggered by the Artifactory UI. | 120 (2 minutes) |
artifactory.aql.streamed.query.timeout | Maximum execution time (in seconds) for streamed AQL queries (when the stream: true header is used). | 7200 (2 hours) |
artifactory.aql.query.timeout.override | Overrides all other timeout values when set. Useful for license-tier-based timeout control. | Not set |
Transitive Search Configuration
The number of remote repositories searched during a .transitive() query on a virtual repository is configurable:
| Property | Description | Default |
|---|---|---|
artifactory.aql.transitive.remote.repos.limit | Maximum number of remote repositories searched within a virtual repository during a transitive query. | 5 |
To increase the limit, add the following line to artifactory.system.properties:
artifactory.aql.transitive.remote.repos.limit=10How Do I Optimize AQL Query Performance?
Index-Friendly Criteria
Use indexed fields first to narrow results efficiently:
| Field | Typically Indexed | Priority |
|---|---|---|
repo | Yes | Use first |
path | Yes | High |
name | Yes | High |
sha256 | Yes | High for lookups |
type | Yes | Medium |
created, modified | Varies | Medium |
| Property keys | Varies | Lower |
Pattern:
items.find({
"repo": "libs-release-local",
"type": "file",
"@custom-prop": "value"
})Limiting Result Sets
Always specify limits to avoid unbounded queries:
// Good
items.find({"repo": "my-repo"}).limit(1000)
// Risky for large repos
items.find({"repo": "my-repo"})| Use Case | Suggested Limit |
|---|---|
| Interactive UI | 50-200 |
| Batch processing | 1,000-10,000 |
| Export/audit | 50,000 (with pagination) |
Avoiding Expensive Patterns
| Pattern | Issue | Better Alternative |
|---|---|---|
{"name": {"$match": "*keyword*"}} | Leading wildcard causes full scan | Use prefix: "prefix-*" |
items.find({}) | No filter at all | Add a repo filter |
Multiple $or with patterns | Expensive | Separate queries |
| Deep cross-domain paths | Many joins | Limit join depth |
| Large offset pagination | Slow skip | Use cursor-based approach |
Include Optimization
Only include what you need:
// Expensive: all fields plus cross-domain
.include("*", "property.*", "stat.*", "artifact.module.build.*")
// Efficient: specific fields
.include("repo", "path", "name", "size")Batch vs. Single Queries
For multiple lookups, combine into one query:
// Instead of N separate queries
// Use one query with $or
items.find({
"$or": [
{"name": "item1"},
{"name": "item2"},
{"name": "item3"}
]
})Frequently Asked Questions
What is the default AQL query timeout?
REST API queries time out after 900 seconds (15 minutes). UI-triggered queries time out after 120 seconds (two minutes). Streamed queries time out after 7,200 seconds (two hours). You can configure all of these via system properties. See What Are the Query Timeout Defaults?.
How do I disable AQL rate limiting?
Set artifactory.aql.queries.limit.enabled=false in your artifactory.system.properties file and restart Artifactory. See Disabling Rate Limiting.
What is the maximum AQL query size?
By default, AQL queries can't exceed 6,000 characters. Queries exceeding this limit receive an HTTP 400 response. You can configure the limit via the aql.search.query.size.limit system property.
How do I increase the transitive search remote repository limit?
Set artifactory.aql.transitive.remote.repos.limit to a higher value in your artifactory.system.properties file. The default is five. See Transitive Search Configuration.
Related Topics
Updated about 2 hours ago
