Performance and Operational Controls
Configure AQL result set limits, query string size limits, query timeouts, and global and per-user rate limiting for JFrog Artifactory. Includes how to get a full .limit() result and optimization best practices for indexing, pagination, and efficient queries.
This page covers result set limits, query string size 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.limitis 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.
How Do I Get a Full .limit() Result?
.limit(N) searches N items before Artifactory checks what you can read. From Artifactory 7.133.0, you can search further and still receive at most N results. Send the scan-factor header on one request, or set the following property so every request on self-managed Artifactory uses it. For the header and a cURL example, see Return the Results You Can Read.
On self-managed Artifactory, add the property to $JFROG_HOME/artifactory/var/etc/artifactory/artifactory.system.properties and restart Artifactory. On SaaS, send the scan-factor header with each request.
| Property | Description | Default |
|---|---|---|
artifactory.aql.query.non.admin.scan.factor | How many times to multiply .limit(N) when the request doesn't include a scan-factor greater than 1. A value of 1 keeps the search at .limit(N). This property applies to every user. | 1 |
artifactory.aql.query.non.admin.scan.factor=1000A scan-factor header greater than 1 overrides this property for that request. A large value searches more items and puts more load on Artifactory.
What Is the Maximum AQL Query String Size?
Artifactory limits the length of the AQL query string that you send to POST /artifactory/api/search/aql. The default maximum is 6,000 characters. This protects the instance when a large query body is posted, for example a large aql.spec file with jf rt curl or curl -d @aql.spec.
The limit applies from Artifactory 7.111.4 (self-managed) and later, and from Artifactory 7.107.1 (SaaS) and later. Queries that ran successfully on earlier versions can start failing after you upgrade if the query text is longer than 6,000 characters.
When the query exceeds the limit, Artifactory does not run the search. It returns HTTP 400 (Bad Request) with this message:
{
"errors": [
{
"status": 400,
"message": "AQL query is too long; please reduce the query length to less than 6000 chars"
}
]
}The number in the message matches the configured limit.
Reduce Query Size
Keep each AQL request at or under 6,000 characters. Practical ways to stay under the limit:
- Split a large
$orlist or long property list into several smaller queries, then combine the results in your script. - Avoid posting a large spec file as the AQL body. Send only the AQL statement, with no extra comments or unused criteria.
- Narrow the query with
repo,path, andnameinstead of enumerating thousands of artifact names.
Configure the Limit (Self-Managed)
On self-managed Artifactory, you can change the limit with artifactory.aql.search.query.size.limit in $JFROG_HOME/artifactory/var/etc/artifactory/artifactory.system.properties. Restart Artifactory after you change the file.
artifactory.aql.search.query.size.limit=6000Warning
Keep the limit at 6,000 characters unless JFrog Support directs you to change it. Raising it toward 8,000 characters can still cause HTTP 500 failures on large or complex queries. Split the query instead. SaaS customers cannot change this property.
How Do I Configure AQL Rate Limiting?
From Artifactory version 7.84, self-managed installations limit how many search and AQL requests can run at the same time. From Artifactory 7.136.0 on SaaS and Artifactory 7.146.7 on self-managed installations, Artifactory can also limit how many of those requests one user can run. This protects Artifactory when many AQL queries run at the same time. When either limit is reached, Artifactory returns HTTP 429 Too Many Requests until a query finishes.
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.user.limit.percent | Percentage of artifactory.aql.queries.limit that one user can run at the same time. Set this to 0 to turn the per-user limit off. Available from Artifactory 7.136.0 on SaaS and Artifactory 7.146.7 on self-managed installations. | 100 |
artifactory.aql.queries.pending.timeout.millis | How long a request waits, in milliseconds, before Artifactory returns HTTP 429. The same wait covers the per-user limit and the global limit. | 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. To leave capacity for other users, set artifactory.aql.queries.user.limit.percent below 100.
Per-User Limit
artifactory.aql.queries.user.limit.percent sets each user's limit as a percentage of artifactory.aql.queries.limit. This limit applies only when artifactory.aql.queries.limit.enabled is true. User agents in artifactory.aql.queries.unlimited.agents aren't limited.
The property accepts the following values.
| Value | Description |
|---|---|
0 or less | Turns the per-user limit off. Only the global limit applies. |
1 to 99 | Sets the limit to that percentage of the global limit. Artifactory rounds the result down. The limit is at least 1. |
100 | Default. Each user can run as many concurrent queries as the global limit allows. |
Greater than 100 | Artifactory treats the value as 100. The per-user limit equals the global limit. |
For example, with artifactory.aql.queries.limit set to 4 and artifactory.aql.queries.user.limit.percent set to 50, each user can run 2 concurrent AQL queries. Other users can still run queries until the global limit of 4 is reached.
On SaaS, you can't change this property. From Artifactory 7.136.0, the value is 100. On self-managed Artifactory 7.146.7 and later, set the property in artifactory.system.properties and restart Artifactory.
artifactory.aql.queries.user.limit.percent=50Artifactory uses artifactory.aql.queries.pending.timeout.millis for both the per-user limit and the global limit. Time spent waiting for the per-user limit shortens the time left to wait for the global limit.
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 Per-User AQL Limit?
The per-user limit controls how many concurrent AQL queries one user can run, as a percentage of the global limit. The default is 100, so each user can use the full global limit. On a self-managed installation, you can set a lower percentage so one user doesn't take every concurrent query. On SaaS, you can't change this property. For more information, see Per-User Limit.
What is the maximum AQL query size?
By default, AQL queries can't exceed 6,000 characters. Queries that exceed this limit receive an HTTP 400 response with the message AQL query is too long; please reduce the query length to less than 6000 chars. See What Is the Maximum AQL Query String Size?.
Why did a previously working AQL query fail after an upgrade?
If you upgraded to Artifactory 7.111.4 or later (self-managed) or to Artifactory 7.107.1 or later (SaaS), Artifactory now rejects AQL request bodies longer than 6,000 characters. Shorten or split the query. Don't raise artifactory.aql.search.query.size.limit above 6,000 unless JFrog Support asks you to.
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.
Why does .limit() return fewer items than I requested?
Artifactory searches N items, then keeps only the ones you can read. You can search further with the scan-factor header or with artifactory.aql.query.non.admin.scan.factor. For more information, see How Do I Get a Full .limit() Result?.
Related Topics
Updated 15 days ago
