We Audited 1,300 Unblock Requests. The Filter Was Wrong 16% of the Time.
90% of unblock requests were for a domain already requested before. One device generated 411 of them. 16% were real overblocks — MIT App Inventor, a kids' coding curriculum, and an Adobe auth endpoint. And 1,265 of 1,300 decisions had no reviewer recorded, which turned out to be our own bug.

Every conversation about web filtering is a conversation about blocking. Vendors sell block rates. IT directors evaluate category coverage. Boards ask whether the filter works.
Almost nobody audits the other direction: what happens when the filter is wrong.
That's the unblock queue — the requests generated when a teacher or student hits a block page for something they legitimately needed. It's the least glamorous surface in the entire product, and it is where your teachers actually form their opinion of your filter. A teacher who waits four days for a coding tool to be approved doesn't conclude "the review workflow needs tuning." They conclude the filter is broken and they start looking for workarounds.
So we audited ours. Every unblock request our platform has ever received, from the first one in February 2026 through last week: 1,300 requests across 205 distinct domains.
Some of what we found was reassuring. Some of it was a defect in our own product that we've since fixed. All of it changed how we think about the second half of filtering.
What we measured, and what we didn't
A note on methodology, because this matters for anyone doing the same audit on their own data.
Everything below is aggregate counts and timing. No student names, no email addresses, no browsing history, no per-student narratives. Domains are named only where the domain itself is the finding — a request for appinventor.mit.edu says something about curriculum, not about a child. Student data in K-12 is radioactive and CIPA, COPPA, and FERPA all apply to exactly this kind of analysis. You can learn everything useful about a request queue without ever opening a student's record.
Every request in this dataset originated from a block page — a student or teacher hit a blocked resource and clicked "request access." That's a meaningful detail: these aren't hypothetical complaints filed later. Each one is a real moment where a real person was stopped mid-task.
Finding 1: 90% of requests are for something already requested
Of 1,300 total requests, 90.2% were for a domain that had already been requested at least once before. 205 distinct domains generated 1,300 requests.
This is the single most important number in the audit, and it reframes the entire problem.
An unblock queue looks like a stream of individual decisions. It is not. It's a small set of unresolved policy questions, each one generating requests over and over until somebody actually resolves it. Every repeat request is evidence that the previous request wasn't truly closed — it was dismissed, or approved for one device instead of the category, or approved and then silently re-blocked by a policy update.
The practical consequence: if you're triaging an unblock queue request-by-request, you are doing roughly ten times more work than the problem requires. Triage by domain, not by request. Sort by request count descending, resolve the top of that list as a policy decision, and the queue collapses.
If your vendor's approval UI doesn't group by domain, that's not a cosmetic gap. It's a workflow that guarantees your admins re-litigate the same 20 decisions all year.
Finding 2: One device generated 411 requests. Volume is not demand.
The single most-requested domain in our entire dataset was gimkit.com, a quiz-game platform, with 411 requests — 32% of all traffic in the queue.
Then we checked how many distinct devices those 411 requests came from.
One.
One device, requesting the same domain 411 times between May 15 and August 17. Not 411 teachers who need Gimkit for class. One person — almost certainly a student — clicking the request button on a block page repeatedly, likely testing whether volume would eventually produce a different answer. Of those 411: 350 denied, 60 dismissed, 1 approved.
This pattern was not isolated. Across the dataset, 19 domains were requested by exactly one device, and those 19 domains account for 466 requests — about 36% of the entire queue.
Here's why this matters far beyond our own dashboard. If you rank your unblock queue by volume — which is the obvious, intuitive thing to do — you will spend your first week of school triaging one determined student's game requests while a genuine teacher request for a curriculum tool sits below the fold. Raw volume is not a demand signal. It's trivially gameable by exactly the population most motivated to game it.
The metric that actually means something is distinct requesters per domain. Three different teachers asking for the same tool once each is a real curriculum need. One device asking 411 times is a student with time on their hands. Those two signals look identical on a volume-sorted list and they call for opposite responses.
Ask your vendor whether their approval queue can deduplicate by requester. If it can't, your prioritization is being set by whoever clicks fastest.
Finding 3: 16% of requests were legitimate — and they were exactly the tools you'd expect
The status breakdown across all 1,300 requests:
| Status | Count | Share |
|---|---|---|
| Denied | 619 | 47.6% |
| Dismissed | 442 | 34.0% |
| Approved | 211 | 16.2% |
| Still pending | 28 | 2.2% |
About one in six requests was a real overblock. That number deserves to be sat with rather than explained away. It means the filter — our filter, tuned by us, on real deployments — was wrong often enough that a sixth of the people who bothered to complain were right.
And the approved domains are the tell. They weren't edge cases. They were:
appinventor.mit.edu— MIT App Inventor, a mainstream intro-to-programming platformbitsbox.com— a kids' coding curriculumword.rodeo— a Wordle-style vocabulary tool teachers use for warm-upsmywordle.strivemath.com— a math-practice word gameims-na1.adobelogin.com— an authentication endpoint for Adobe
That last one is a category of failure worth naming separately. ims-na1.adobelogin.com isn't a destination anybody browses to. It's the login service Adobe products call in the background. When a filter blocks an auth endpoint, the user-visible symptom isn't a block page — it's "Adobe is broken." Nobody files a ticket saying "please unblock ims-na1.adobelogin.com," because nobody knows that's the problem. It generated 77 requests before it was resolved.
The pattern in that list: educational tools that look like games, and infrastructure that looks like nothing. Those are the two blind spots of every category-based classifier. A vocabulary game and a time-wasting game are structurally identical — same canvas rendering, same interaction loop, same score counter. The only difference is pedagogical intent, which is not a property a classifier can observe from traffic.
This is a real limitation of AI-driven filtering, ours included. The honest answer isn't "our classifier is smarter." It's that any system this aggressive on games will catch educational games, so the recovery path — the unblock queue — has to be fast and trustworthy. Detection accuracy and correction speed are the same product feature. Most vendors only sell you the first half.
Finding 4: The audit trail was missing on 97% of decisions — and that was our bug
This is the finding we least wanted and most needed.
Of 1,300 requests, 1,265 had no reviewer recorded and no review timestamp. Broken out by status:
| Status | Total | Has reviewer + timestamp |
|---|---|---|
| Denied | 619 | 26 |
| Dismissed | 442 | **0** |
| Approved | 211 | 9 |
| Pending | 28 | 0 (correctly) |
Every single one of the 442 dismissed requests had no record of who dismissed it or when. Not one.
We traced it in our own source. Two code paths write to the request table. The teacher-portal path does it correctly — it sets status, reviewed_by, reviewed_at, and a review note in a single statement. The admin dashboard path builds its update dynamically, and the field that stamps the reviewer is only appended when a reviewer was explicitly supplied by the caller. Bulk actions in the UI didn't supply one. So the status changed, the request disappeared from the queue, and nothing recorded that a human had ever touched it.
The result is a queue that looks clean and can't be audited. You cannot answer:
- Who denied this teacher's request for a curriculum tool?
- Was it reviewed by a person, or bulk-cleared to zero the badge count?
- If the same domain is requested again next month, what was the reasoning last time?
That last question is the operational cost, and it links directly back to Finding 1. A decision with no recorded reasoning is a decision that will be made again from scratch. The 90% repeat rate and the 97% missing-audit rate are the same bug viewed from two angles.
We found this by auditing our own queue, and the fix is queued: both write paths need to stamp reviewer and timestamp unconditionally, with bulk actions attributed to the acting admin. The historical rows will stay blank regardless — you can't retroactively invent an audit trail, which is precisely why this is worth catching before you have 1,300 of them.
If you take one thing to your own vendor, take this one. Open your approval queue, pick a resolved request, and ask who resolved it and when. If the interface can't tell you, you don't have an approval workflow — you have a delete button with extra steps. It's a two-minute test and it's the kind of thing that only becomes visible when a parent or a board member asks why a specific resource was blocked.
Finding 5: Median review was 20 hours. The tail was four months.
For the 35 requests where we can actually measure it (the audit-trail gap above limits the sample — a real caveat, not a footnote):
- Median time to review: 19.8 hours
- 90th percentile: 2,048 hours — roughly 85 days
- Mean: 304 hours, dragged there entirely by the tail
And the requests still open right now: 28 pending, averaging 91.7 days old, with the oldest at 94.4 days.
Those 28 have been sitting since roughly the end of May. School let out, the queue stopped being checked, and nothing ever escalated them. They will still be there when teachers walk back in — three-month-old requests from people who long ago concluded that asking doesn't work.
The median is genuinely fine. Under a day is a reasonable answer for a policy question that needs a human. The distribution is the problem, and a median will never show it to you. A queue where half of everything is handled in 20 hours and a tenth of it waits three months isn't a fast queue with some outliers. It's two different systems: an attentive one for requests that arrive when someone's watching, and an oblivion for everything else.
Every unblock queue needs an age-based escalation rule, because nothing else catches this. Concretely:
- Nothing sits unreviewed past one school day. A teacher who asked Monday morning has an answer by Tuesday morning, even if the answer is no.
- Anything past 72 hours escalates to a named human, not a shared inbox.
- The queue has a hard floor of zero at term boundaries. June and August are when requests go to die.
- Track p90, not average. Averages hide tails, and the tail is where trust is lost.
Finding 6: The block page is a product surface, and it's doing more work than you think
One structural detail: every request in this dataset came from the block page. Not from email, not from a helpdesk ticket, not from a form on the intranet. All 1,300.
Which means the block page is not an error screen. It's the highest-traffic input in the entire filtering workflow — the one place where the person who was just interrupted is still present, still motivated, and still knows exactly what they were trying to do. Twenty minutes later that context is gone and they've either found a workaround or given up.
Most block pages waste that moment completely. A red banner, a policy code, maybe an email address for IT. Everything useful about the interruption evaporates.
What the block page should capture, while the user is still there:
- The full URL, not just the domain —
sites.google.comis both a curriculum host and the single largest source of unblocked games, and the path is what distinguishes them - Who is asking, and in what role — teacher requests and student requests are different signals and should never be pooled
- Why, in one field — "we use this in 7th grade math on Fridays" resolves in seconds; a bare domain requires investigation
- The category the filter assigned — this is how you find classifier drift, and it's why 1,269 of our 1,300 requests having no recorded category is its own small failure
That last gap is worth naming: only 31 of 1,300 requests carry the category that triggered the block. Without it, you can see that something was blocked but not why the classifier thought so, which makes systematic tuning impossible. You end up fixing 205 domains one at a time instead of finding the two rules that misfire.
The audit you can run this week
None of this required special tooling. If you have any filter with an approval queue, you can reproduce the whole thing:
- Export every request since the start of last school year. Not the open ones — all of them. The resolved ones hold the findings.
- Count distinct domains vs. total requests. A ratio far above 1 means you're re-deciding the same questions. Ours was 6.3 to 1.
- Count distinct requesters per domain, then re-sort. Compare that ranking to the volume ranking. If the top of the two lists disagree, your triage order is wrong.
- Check the audit trail on resolved requests. Who, and when. If those fields are empty, stop and fix that before anything else.
- Compute p50 and p90 review latency. Ignore the mean.
- Find the oldest pending request. If it predates the current term, your queue has no escalation path.
- Look at what you approved. Those domains are your classifier's blind-spot map, and they're the highest-value input you'll ever get for policy tuning.
Then do the thing that costs nothing and tells you the most: ask three teachers what happens when they hit a block page. If any of them describes a workaround — a personal hotspot, a phone, an unfiltered device in the library, "I just don't use that site anymore" — your unblock queue has already failed, regardless of what the numbers say.
Why we published our own bad numbers
A 16% overblock rate and a 97% missing-audit-trail rate are not flattering figures for a filtering vendor to publish.
We're publishing them because the alternative is the thing we find genuinely objectionable about this market: every vendor in K-12 filtering markets detection, and nobody markets correction. Block rates, category counts, AI accuracy, threat feeds. Nobody ships a number for how fast a teacher gets unblocked, because that number is always embarrassing and nobody is asked for it.
But detection and correction are not separate features. A filter that blocks aggressively and corrects slowly is worse in practice than a filter that blocks less and corrects in an hour — because the first one teaches an entire building to route around it, and a filter people route around protects nobody. The 411-request device and the 94-day-old pending request are the same failure: a system that stopped being believed.
We found our audit-trail bug because we went looking in the least interesting place in the product. If you run the same audit on your current filter, you will find something too. That's not an argument for switching vendors. It's an argument for looking.
If you want to see what this looks like when the approval workflow is actually instrumented — grouped by domain, deduplicated by requester, with an audit trail on every decision and escalation on anything older than a school day — start a free 30-day pilot. No contract, no credit card, no sales call. Bring your own worst-case queue and we'll compare notes.
Related Reading
- Your Safety Alerts Are Working. They're Still Failing.
- Alert Fatigue Is the Real Failure Mode of Student Safety Monitoring
- Managing Teacher Expectations: How to Roll Out a New Web Filter Without the Pushback
- Why 'Whitelisting' is a Disaster for Teacher Creativity (And How AI Solves It)
- The End of Unblocked Games: Inside KyberGate's 8-Layer Game Detection Engine
- How to Choose a Web Filter for Your School District: The 2026 Buyer's Guide
Ready to protect your students?
Deploy KyberGate in under 30 minutes. No hardware required.
Request a Demo