Skip to content

Thunderbird Running Slow or Beachballing — A Diagnostic Playbook

TL;DR — Thunderbird slowness usually has one of three causes, and they look alike until you isolate them: (1) profile bloat — a giant Gmail "All Mail" mbox and an oversized global-messages-db.sqlite search index; (2) a half-built/corrupt gloda index; or (3) the problem isn't Thunderbird at all — a degraded system state (e.g. a long-uptime macOS WindowServer) that stalls any heavy redraw. Work the cheap, decisive tests in order: profile size → fresh-profile test → "do other apps misbehave too?" Don't start deleting things before you've localized the layer.


Symptom

Two distinct flavors, often confused:

  • General sluggishness — slow startup, folder-switching, and search; the whole app feels heavy.
  • Per-action stall / beachball — the app idles fine, but clicking a message (or some other specific action) freezes the UI for a second or more, every time.

They have different causes. Identify which you have first.


Layer 1 — Profile bloat (most common cause of general sluggishness)

Check the profile size and its two usual offenders:

# macOS profile path; Linux: ~/.thunderbird/<profile>
P=~/Library/Thunderbird/Profiles/*.default-release
du -sh $P
ls -lh $P/global-messages-db.sqlite          # the gloda search index
find $P -type f ! -name '*.msf' -size +500M  # largest message stores (mbox)

Red flags:

  • global-messages-db.sqlite over ~1 GB — gloda (the global search index) bloats startup, search, and folder-switching once it gets this big.
  • A multi-gigabyte [Gmail]/All Mail mbox — Gmail's "All Mail" is a copy of every message already present in your other folders/labels. Keeping it offline doubles disk usage and indexing work for zero benefit.

Fix: stop syncing Gmail "All Mail" (and "Important")

These two Gmail folders are pure duplication. Exclude them at the source:

  1. Gmail web → Settings → Labels → for All Mail and Important, uncheck "Show in IMAP." (This option is on the Labels tab — it is not on the IMAP settings page in modern Gmail.)
  2. In Thunderbird, the folders stop syncing entirely.

The gotcha: disabling offline storage does NOT reclaim disk

Turning off "Keep messages in this folder on this computer" (Account Settings → Synchronization & Storage → Advanced) clears the offline flag but leaves the already-downloaded bodies on disk. And Compact Folders won't remove them either — Compact only purges deleted/expunged messages, and those All-Mail messages are all still live on the server, so Compact has nothing to remove.

You can confirm the stranded cache in folderCache.json (offlineFlag = off but folderSize/localSize still huge).

To actually reclaim it, with Thunderbird fully quit and offline already disabled (so nothing is lost — it all lives on the server), delete the local store files for those folders:

# Thunderbird must be QUIT. Move (don't hard-delete) so it's reversible:
mkdir -p ~/tb-reclaim-bak
mv "$P/ImapMail/imap.gmail.com/[Gmail].sbd/All Mail"{,.msf} ~/tb-reclaim-bak/
# ...repeat for Important and any orphaned [Gmail]All Mail store

On relaunch Thunderbird rebuilds empty, header-only stores (no body re-download, since offline is off). Verify your mail still opens, then delete the backup.


Layer 2 — A corrupt or half-built gloda index (per-action stalls)

If opening a message stalls every time — including messages you've already opened — it isn't a network fetch (a cached message would be instant on re-open). The message-display pane queries gloda for the conversation/"related messages," and querying an incomplete or interrupted index stalls on every render.

Fix — delete the index and let it rebuild fresh (Thunderbird quit):

rm -f "$P"/global-messages-db.sqlite "$P"/global-messages-db.sqlite-{wal,shm,journal}

It rebuilds on next launch. A full rebuild is heavy — let it finish uninterrupted, ideally overnight. If you must stop the churn temporarily, set mailnews.database.global.indexer.enabled = false in prefs.js (this disables global/quick-filter search until re-enabled; per-folder search still works).


Layer 3 — It's not Thunderbird (the beachball that survives everything)

If a per-message beachball persists after you've ruled out the index, run these two decisive splits:

Profile vs. app — the fresh-profile test

Spin up a throwaway profile with real mail to click, leaving your real profile untouched:

TEST=~/tb-test-profile
mkdir -p "$TEST/Mail/Local Folders"
cp "$P/ImapMail/imap.gmail.com/INBOX" "$TEST/Mail/Local Folders/Inbox"   # mbox only; TB rebuilds the .msf
open -a Thunderbird --args -profile "$TEST" -no-remote                    # macOS; close the account-setup tab
  • Smooth in the fresh profile → your real profile is the problem (repair/migrate it).
  • Still beachballs → it's the app or the environment, not your data.

Also try Troubleshoot Mode (open -a Thunderbird --args -safe-mode), which disables add-ons and hardware acceleration in one shot.

App vs. system — "do other apps misbehave too?"

Click around in Finder, a browser, etc.

  • Other apps also stutter → it's a system/graphics problem, not Thunderbird. Thunderbird (a Gecko app) renders heavily and is often the first thing to stall when the OS compositor is degraded.
  • Only Thunderbird → the app binary (try reinstalling) or a version regression.

Long-uptime degradation (a real, easily-missed cause)

On macOS, a WindowServer that has been running for weeks under memory pressure can accumulate leaked surfaces and degrade — stalling any heavy redraw, including rendering a new email, while leaving lighter native apps fine. Check for it:

uptime
ps -o etime=,time=,%cpu= -p "$(pgrep -x WindowServer)"   # huge accumulated cputime = degraded
sysctl -n vm.swapusage                                   # GBs of swap in use = sustained pressure

If uptime is in the weeks, swap is heavily used, and WindowServer shows hours of accumulated CPU, just reboot. It clears the compositor and flushes swap — and it's the cheapest fix on the list, so consider it early when the symptom is system-wide.


Profiling a stall without symbols

Thunderbird ships stripped, but you can still tell what kind of stall it is. Sample the process while reproducing it:

sample "$(pgrep -x thunderbird)" 5 -file /tmp/tb.txt   # click messages during the 5s

In the main-thread (com.apple.main-thread) subtree:

  • Mostly CPU-busy frames in XUL → genuine computation (rendering/layout/parsing) — points at the app/render path.
  • Mostly mach_msg / kernel wait frames → blocked on I/O or network, not CPU — points at disk contention (e.g. a backup hammering the disk) or on-demand body fetch.

This single distinction saves a lot of wrong turns.


Quick reference — work it in this order

  1. du -sh the profile; check global-messages-db.sqlite size and the largest mbox stores.
  2. Exclude Gmail All Mail / Important via Labels → "Show in IMAP"; reclaim stranded local stores (TB quit).
  3. Per-message stall? Delete the gloda index and rebuild.
  4. Still stalling? Fresh-profile test (profile vs. app) and "other apps too?" (app vs. system).
  5. System-wide and long uptime? Reboot — and check it first next time if the whole machine feels heavy.

Key takeaways - Gmail "All Mail" is duplicated mail — keep it offline-disabled / not shown in IMAP permanently. - Disabling offline storage and Compact do not reclaim an existing local cache of server-live messages; only deleting the store files does. - "Beachball on every message, even re-opened" = per-display work (index/render), not a fetch. - A fresh-profile reproduction means it's not your data; other apps stalling too means it's not Thunderbird. - On long-uptime machines, a degraded compositor masquerades as an app bug. Reboot is a legitimate — and cheap — fix.