TLDR: Slack's new rate-limit tier can make deep history pulls nearly impossible — but the docs don't tell you which tier you're on. Probe the wire before you build the feature.
The Setup
I was adding a 90-day Slack scrollback cache to my personal AI operations cockpit (powered by Claude via Arcade, my MCP auth provider).
The feature was simple to describe: pull the full message history for each of my three businesses — an ecommerce business, a second business, and a third business — cache it locally, surface it in a unified timeline.
Simple to describe. Not simple to commit to.
The Wall I Hit (Before Writing a Line of Code)
Slack quietly changed how rate limits work for newer apps.
Non-Marketplace apps created after roughly May 2025 got moved to a punishing regime: conversations.history and conversations.replies capped at something like 1 request per minute and 15 objects per request.
Old Tier-3 behavior was ~50 requests/minute with hundreds of objects per call.
That's not a performance difference. That's a fundamentally different product.
The brutal part? You cannot tell from the docs which tier you're on. It depends on when your app was created. There's no endpoint that tells you. There's no dashboard flag. The docs describe both regimes and give you zero signal about which one applies.
This was the go/no-go gate for the whole feature. If we were under the strict cap, a 90-day deep backfill wasn't just slow — it would take days, if it ran at all.
What I Did Instead of Guessing
I probed the actual wire.
The Arcade Slack token is shared across all three businesses on a single OAuth client. I dropped into a raw HTTP call using client.get_http_client() — bypassing the MCP tool layer entirely — and fired a live GET conversations.history?limit=200 against an ecommerce business DM channel.
Three things came back:
- 19 messages returned in one call → the 15-object cap does NOT apply
- Three rapid-fire repeats, all
200, noRetry-Afterheader → not under the 1-per-minute cap - A
next_cursoron a second business DM → cursor pagination works, deep backfill is feasible
We're on the generous tier. Feature is go.
Why I Still Built It Defensively
Finding out you're on the good tier doesn't mean you skip the guard rails.
The feature is cursor-paginated, idempotent, and retries on 429. Because the tier can change, and because I might one day build the same pattern for a newer app that IS under the cap.
The code shouldn't know or care which regime it's running against. Retry-on-429 with backoff, cursor pagination, skip-if-already-cached. Those aren't belt-and-suspenders for the paranoid. They're the contract.
Why This Matters to Me
I've built enough integrations to know that the thing that kills features isn't bad ideas — it's invisible constraints you discover after you've already committed to the architecture.
The Slack rate-limit tier is a perfect example. It's invisible in the docs, it's not surfaced in any UI, and it varies by app age. The only way to know is to ask the wire directly.
Probe first. Build second. And build defensively regardless of what the probe says.
P.S. If you're using Arcade and the shared Slack client across my three businesses — this was verified live on 2026-06-23. If you're on a newer Slack app entirely, do NOT assume you have the same regime. Run the probe.