Cross-Project JQL Filters vs. Foundation Sync Agents
JQL is a query. A Sync Agent is a standing rule that writes JQL results into a hierarchy. JQL returns a flat list and re-runs when you refresh. Sync Agents maintain parent/child structure and update automatically on Jira product events. If you need a live cross-project tree, a query alone won't build it.
What is cross-project JQL, and where does it fit?
Jira Query Language (JQL) is the search grammar built into Jira. A query like project in (FOUND, PLAT) AND issuetype = Epic AND status != Done returns every open Epic in both projects as a flat result set. It spans any number of projects, supports dozens of fields and operators, and costs nothing extra.
JQL fits ad-hoc search, saved filters, dashboard gadgets, and automation triggers. It is read-only — a query answers “what issues match this right now?” and nothing else. It returns a flat list; the dashboard gadgets that render JQL results cap out around 100 issues per gadget, one query per gadget. For a cross-project view — hierarchical, persistent, editable — you have to move beyond raw JQL.
What is a Sync Agent, and how is it different from a JQL filter?
A Sync Agent is Foundation's standing rule that takes JQL as input and continuously writes matching issues into a Lens as children of a parent node. You attach it to a parent (an Epic, a program-level Flex Item, a milestone), give it JQL, and Foundation pulls every match into that parent's subtree. New issues that match are added automatically; issues that stop matching are removed.
Example: the JQL project = PLAT AND fixVersion = "Q2 Release" in a dashboard gadget shows 47 flat rows. The same JQL attached to a Sync Agent under a “Q2 Release” Flex Item places those 47 issues as children in a live tree — and when issue #48 is created tomorrow, it appears there automatically.
This pattern is not unique to Foundation. Tempo's Structure calls them Generators; BigPicture calls them Sync Rules. The core idea is the same: JQL-in, hierarchy-out, maintained on events. Differences are in pricing, platform (Forge vs. Connect), scope caps, and update latency.
How does each handle new issues that match?
This is where the models diverge. A JQL filter is pull-based: the query runs only when a user refreshes the search page, opens a dashboard, or an automation rule fires. Between those moments, newly-created matching issues are invisible until the next re-run.
A Sync Agent is push-based via Jira product events. Foundation subscribes to avi:jira:created:issue and avi:jira:updated:issue. When Jira fires either, Foundation checks whether the changed issue matches any Sync Agent's JQL and updates the relevant parent within seconds. No refresh, no polling interval. A Lens built from Sync Agents is self-maintaining — the tree updates itself as Jira activity flows through the cache.
How do performance and Jira API rate-limits differ?
Both consume Jira REST API points, but in very different shapes. Every JQL search costs points — the Atlassian schedule charges roughly 1 point plus 1 per result. A dashboard gadget returning 100 issues costs ~101 points per render. Ten users opening that dashboard burns 1,010 points per refresh cycle.
Sync Agents flip the cost profile. The initial JQL scan costs points, but after that, events are free. Foundation's issue cache stores fetched data in Forge SQL, so routine views don't touch the Jira API. A dashboard strategy scales linearly with viewers; a Sync-Agent Lens has fixed ingest cost and effectively zero cost per view.
Which one builds a hierarchy?
Only the Sync-Agent approach builds a hierarchy. JQL has no concept of parent/child in its output — the Jira search API does not return trees. A query like project = FOUND AND issuetype = Epic returns a flat list of Epics with no way to say which initiative owns each one.
Sync Agents build hierarchy by combining two primitives. Each Sync Agent has a parent node in the Lens — the node its results become children of. A second agent type, Child Extend, recursively pulls the Jira children of already-synced issues (Stories under Epics, Subtasks under Stories). Stack them: a JQL Insert finds all open Epics; a Child Extend pulls their Stories; another pulls Subtasks. You get a four-level tree from two or three queries, alive on events. Foundation's Lenses are the hierarchical surface; Sync Agents populate them.
What's the cost difference?
JQL is free — part of every Jira Cloud license, with unlimited saved filters and dashboard gadgets. If flat gadgets genuinely meet your reporting needs, there's no reason to add a PPM app.
Foundation is a paid Marketplace app (free tier up to 10 users); Structure and BigPicture are paid suites. The practical test: if you're rebuilding the same report weekly — once as a JQL filter, once as a spreadsheet that aggregates Epics with Story rollups — you're paying in time what a Sync Agent would automate. Above ~200 issues across more than two projects, maintenance burden typically exceeds license cost within a quarter.
When should you use which?
| Dimension | Cross-project JQL filter | Foundation Sync Agent |
|---|---|---|
| Refresh model | Pull on user refresh (flat re-run) | Push on Jira product events (seconds) |
| Hierarchy | No — flat result list only | Yes — places results under a parent node |
| Rate-limit cost per view | ~1 + N points per refresh per viewer | Free (served from cache; events are free) |
| Scope | Any JQL across any projects | Any JQL across any projects (1,000-issue Lens cap in MVP) |
| Write-capable | No — query only | Yes — writes into Lens hierarchy; inline edit writes back to Jira |
| License required | None (built into Jira) | Foundation (free tier up to 10 users) |
Use JQL on its own when the view is flat, ad-hoc, or sits inside a dashboard a handful of people check occasionally. Use a Sync Agent when you need a persistent hierarchical view, when many people open it frequently, when it must stay fresh without anyone refreshing, or when you want to edit issues inline from a cross-project rollup.
The two aren't mutually exclusive. Most Foundation customers keep their saved filters for ad-hoc work and reference those same filters from Sync Agents that power the Lenses leadership reviews weekly. The JQL you've already written is the input; the Lens is the durable output.
Frequently asked questions
Can I build a hierarchy just by writing a clever cross-project JQL?
No. JQL returns a flat result set. A query like project in (FOUND, PLAT) AND issuetype in (Epic, Story) returns all matching issues as one unordered list — there is no parent/child structure in the response. To show a hierarchy you need a tool that reads JQL results and then writes them into a tree, which is exactly what Foundation’s Sync Agents, Structure’s Generators, and BigPicture’s Sync Rules do.
How often does a Sync Agent re-check for new issues?
Foundation’s Sync Agents listen for Jira product events (avi:jira:created:issue, avi:jira:updated:issue). When a new issue is created or an existing issue is modified in a way that affects a Sync Agent’s JQL, the agent updates the Lens within seconds. There is no polling interval to configure. Product events are free — they do not consume Jira REST API rate-limit points.
If JQL is free, why would I pay for a PPM app to do what JQL already does?
JQL is a query language. It returns results but does not build anything. You still need a surface to display results (Jira’s search page, a dashboard gadget), and that surface is flat, capped at a few hundred issues, and has no grouping beyond one JQL per gadget. A PPM app adds hierarchy, persistent views, inline editing across projects, and Gantt/Timeline visualization — none of which JQL alone provides.
Do Sync Agents replace Jira filters, or should I keep my saved filters?
Keep your filters. Sync Agents consume JQL — often the same JQL you’ve already tuned in a saved filter. You can paste the filter’s JQL into a Sync Agent, or reference the filter directly (e.g., filter = "All Open Epics"). Filters remain useful for ad-hoc queries, dashboard gadgets, and automation rules; Sync Agents turn that filter into a live hierarchy inside a Lens.
What happens when an issue no longer matches the Sync Agent’s JQL?
By default, Foundation removes it from the Lens on the next event-driven update. For example, if a Sync Agent is JQL status != Done and you transition an issue to Done, it disappears from the Lens within seconds of the transition event firing. This is usually what you want for active-work views — but for historical reporting you’d use a JQL clause that captures completed work too.
Will Sync Agents work across unlimited projects, or is there a project cap?
Sync Agents operate on whatever JQL you provide, across any projects the running user can see. There is no project count limit — a Sync Agent with JQL project in (A, B, C, D, E, F) works the same as one with a single project. The MVP cap you’ll hit first is the 1,000-issue-per-Lens ceiling, which applies regardless of how many projects contribute to that Lens.
Related guides
- Cross-Project Jira Reporting — pillar guide
- How to see all Jira issues across projects in one view
- Rolling up story points across Jira projects
- Sync Agents: automated hierarchy building with JQL
- What is a Lens? Foundation's cross-project portfolio view
Sources
- Configure advanced issue search with JQL — Atlassian support
- Advanced search reference — JQL fields — Atlassian support
- Jira Cloud REST API rate limits — Atlassian developer docs
- Forge Jira events reference — Atlassian developer docs
- Structure by Tempo — Atlassian Marketplace
- Foundation for Jira — Atlassian Marketplace listing