Nothing in the plugin hooks user deletion. grep -rn "deleted_user\|wpmu_delete_user\|remove_user_from_blog" includes/ presence-api.php returns nothing; includes/lifecycle.php:40 is the logout handler, not a delete handler.
A deleted user's rows in each site's {prefix}presence table survive until they age out on TTL, and that site's network summary row keeps naming the ID until its next push. So for up to one TTL the network reports a headcount that includes an account that no longer exists.
The read path compensates. wp_presence_filter_network_snapshot_users() in includes/network-functions.php runs one get_users( include, fields => ID ) over every user online anywhere on the network on every network-admin request, purely so the counts are right during that window. Measured on a seeded network of 1000 sites x 15 users:
|
cold read |
| with the existence query |
39.0 ms |
| existence query short-circuited |
19.5 ms |
Half the read path exists to cover a hook that was never added.
Fix: hook deleted_user (and remove_user_from_blog) to delete the user's presence rows and re-push the affected sites, then reconsider whether the read-path filter is still worth its cost.
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Assisting with analysis
Nothing in the plugin hooks user deletion.
grep -rn "deleted_user\|wpmu_delete_user\|remove_user_from_blog" includes/ presence-api.phpreturns nothing;includes/lifecycle.php:40is the logout handler, not a delete handler.A deleted user's rows in each site's
{prefix}presencetable survive until they age out on TTL, and that site's network summary row keeps naming the ID until its next push. So for up to one TTL the network reports a headcount that includes an account that no longer exists.The read path compensates.
wp_presence_filter_network_snapshot_users()inincludes/network-functions.phpruns oneget_users( include, fields => ID )over every user online anywhere on the network on every network-admin request, purely so the counts are right during that window. Measured on a seeded network of 1000 sites x 15 users:Half the read path exists to cover a hook that was never added.
Fix: hook
deleted_user(andremove_user_from_blog) to delete the user's presence rows and re-push the affected sites, then reconsider whether the read-path filter is still worth its cost.Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Assisting with analysis