Skip to main content

How to Find Stale Pages in Confluence (Free, Premium and Enterprise)

· 10 min read
Quick Answer

On Premium and Enterprise, open Space settings → Content manager and use the Last active dropdown — it shows pages not viewed, updated or commented on, with options from 7 days to 6 months back. On Free and Standard that screen does not exist, so use CQL instead: type = page AND lastModified < now("-365d") ORDER BY lastModified ASC. Neither route is complete: Atlassian documents that Last active excludes pages with children, and blogs sit outside the tool entirely.

A Confluence instance does not rot all at once. It accumulates. A project wraps up and its space stays. A team splits and both halves keep the old runbook. Someone copies a page instead of linking to it, and now two versions exist with different numbers in them. Five years later a new hire searches for the onboarding doc, lands on the 2021 version, and trusts it.

The cleanup instinct is right. The problem is that "find stale pages" is one of those tasks where the answer depends entirely on which Confluence plan you happen to be on, and almost nobody knows that until they go looking. Here is what each tier actually gives you, in the order you should try it.

What you'll learn
  1. The native way, and the four documented omissions
  2. Why Atlassian deliberately skips your most-outdated pages
  3. The CQL query that works on every plan, including Free
  4. Why "not edited" and "nobody reads it" are two different lists
  5. What to do with the list once you have it

The native way: content manager (Premium and Enterprise)​

Confluence ships this tool and it does one specific job. Per Atlassian's documentation, it is an admin tool in Confluence Premium and Enterprise, and Confluence Standard users have no access to it.

Space settings → Content manager → Last active

The filter shows pages that haven't been viewed, updated or commented on. The dropdown offers four fixed options: Over 7 days ago, over 1 month ago, Over 3 months ago, Over 6 months ago. From there you can archive (up to 500 items at a time), delete (up to 100), change owner, change status, or apply an automation flow to the selection.

Three things about it are worth knowing before you plan a cleanup around it.

Limit 1 — it is one space at a time​

The tool lives under Space settings and operates on a single space. There is no site-wide version. If you run 40 spaces, an instance-wide audit means opening the same screen 40 times and merging the results yourself. That is a common reason people end up writing a script instead.

Limit 2 — it skips every page that has children​

This one is documented, though the wording deserves care. Atlassian's content manager page states:

"Last active" won't return a complete list. It specifically filters pages that don't have children. This serves as a safety measure due to the way permissions are inherited in Confluence. — Atlassian: Clean up a space with the content manager

Read that literally and it reads as excluding childless pages. That is almost certainly a wording slip in the docs, because the rationale only makes sense the other way round: nested content inherits view permissions from its parent, so the risk being guarded against is acting on a parent without first setting explicit permissions on each page. Administrators consistently report the observed behaviour as parent pages with children being the ones left out of the list.

Either way, the conclusion for you is the same, and it is the part that matters: the list is not complete, and the pages most likely to be out of date are parent pages. The failure mode is quiet. You get a short list, it looks complete, and you archive what is on it — while the stale parents stay exactly where they were, and you conclude the cleanup worked. If you are about to run a cleanup on a space with a deep page tree, spot-check three parent pages by hand first.

Limit 3 — more is excluded than the filter name suggests​

The same documentation lists what the content tree covers and what it does not:

IncludedExcluded, and why
Published pagesBlogs — the tool organizes a space's content except blogs
WhiteboardsDrafts — excluded because they are only visible to their author
Folders, live docs, smart linksDatabases — excluded while still in beta

So the Last active filter is a filter within an already-narrowed set. Blog posts are not in the tool at all, which matters if your stale content lives in blog posts.

Which plan do I have?

Atlassian's documentation notes that Confluence Standard users don't have access to the content manager, and points them instead to archiving or deleting a nested group — including its nested pages — from the content tree. If you're on Free or Standard, everything below this section is your answer.

The route that works on every plan: CQL​

Confluence Query Language runs on Free. It is less comfortable than a filter dropdown, but it is not limited to one space, and you can export what it returns. The syntax below follows Atlassian's official CQL reference.

type = page AND lastModified < now("-365d") ORDER BY lastModified ASC

Narrow it as needed:

space = ENG AND type = page AND lastModified < now("-180d") ORDER BY lastModified ASC

Run it in Advanced search in the Confluence UI, or via the REST API if you want the results programmatically:

curl -u "you@example.com:token" \
--get "https://your-domain.atlassian.net/wiki/rest/api/content/search" \
--data-urlencode 'cql=type = page AND lastModified < now("-365d") ORDER BY lastModified ASC' \
--data-urlencode "limit=100"

Response bodies paginate — follow _links.next until it is absent, or you will silently process the first batch and believe it is the whole set.

Useful variations, all taken from Atlassian's documented Confluence CQL fields:

GoalAdd to the CQL
Several spaces at onceAND space in (ENG, OPS)
Only blog postsAND type = blogpost
Only pages still in draftAND pageStatus = "Rough draft"
Scope to one page treeAND ancestor = 12345 (the parent page's content ID)
Skip a known-good areaAND space != ARCHIVE
Pages carrying a Jira macroAND macro = jira

Two details worth knowing. text is a master field covering page title, content body and labels together, so a text ~ query is broader than it looks. And label exclusions use NOT IN rather than an empty-value test: label not in (draft, review) means does not carry either of these labels, not carries no labels.

The trap: last modified is not the same as stale​

This is the part that turns a cleanup into a mistake.

lastModified measures editing. It does not measure reading. The two lists are close enough to look interchangeable in a spreadsheet, and far enough apart to archive something important.

PageLast modifiedRead?Verdict
GDPR data-processing register14 months agoread every quarter by Legalkeep — reference material is meant to be static
Onboarding checklist2 weeks agoread by nobody, everarchive — recent does not mean useful
TEST-page-final-v23 years agozero viewsarchive now
Incident runbook8 months agoread weekly by on-callkeep — nobody edits a runbook until it breaks

That first row is the one that gets people. A reference page that is read constantly and never edited looks maximally stale by the lastModified measure and is the last thing you should archive.

Confluence itself doesn't settle this for you. In Atlassian's own words, the product "does not have a native function for tracking historical page views", and the feature request asking for a last-viewed page property (CONFSERVER-33386) is still open. (That article is written for Data Center, where the answer is a database query — but the underlying gap it describes is why the built-in filters on Cloud fall back to activity you can see rather than activity you can't.) View analytics do exist, but the content insights panel that carries a last-viewed value is a Premium and Enterprise capability — basic view counts sit lower, but the last-viewed field is in the paid tier.

caution

lastModified < now("-365d") means the page has not been edited for a year. It does not mean the page is wrong. Confirm what each page contains before you act on it, and archive rather than delete wherever you have the choice.

What to do with the list​

Once you have candidates, sort into three buckets before you touch anything:

  1. Archive. Unused, superseded, or a copy of something that still exists. Archived content drops out of the content tree and can still be viewed — which is why archiving is reversible and deleting is not.
  2. Flag and notify. Content someone still depends on that is quietly out of date. Label it needs-review, or use the content manager's automation flow to route it to the last editor. This is the bucket most cleanups skip and most need.
  3. Keep. Reference material, compliance documents, anything read regularly without being edited.

Two operational notes that save pain later:

  • Deleting does not create redirects. When a page is permanently deleted, inbound links break. Check what links to a page before you remove it.
  • Trash is not a backup. Deleted content can be restored from trash until it is purged. If you are deleting more than a handful of pages, export the space first.

Doing this on a schedule​

Once a quarter is a sensible cadence, and Atlassian's own guidance in the content manager documentation is explicit about the split: use the content manager for heavy bulk cleanup, and use automation flows — which the same page describes as another premium feature — to keep things tidy moving forward.

On Free and Standard you are re-running the CQL query by hand each quarter. That is the practical difference between the tiers, and it is also the reason demand for third-party tooling in this specific area exists at all: the native feature is well built, and unavailable to Free and Standard.

Sources​