At a glance
| Problem | Two per-user existence checks while serializing each active user’s 2FA status |
| Scope | GET /admin/users/list/active.json in Discourse’s Rails application |
| Result | 66.5% lower mean server duration and 93.7% fewer SQL events for 75 active users |
| Delivery | Regression-tested open source change merged upstream |
The problem
Discourse’s admin active-users endpoint reports whether each user has two-factor authentication enabled. During serialization, the checks for an enabled TOTP method and an enabled security key each issued an existence query for every user.
With 75 active users and no configured 2FA records, the endpoint performed 75 TOTP existence queries and 75 security-key existence queries. Those repeated checks accounted for nearly all of the request’s 159 SQL events and produced 148 duplicate query fingerprints.
What I changed
I moved the work from per-user database checks to association-aware lookups:
- the admin user query now preloads both enabled TOTP records and enabled security keys;
totp_enabled?uses the loaded TOTP association;- security-key and passkey checks search the loaded security-key collection by factor type; and
- when security keys have not been preloaded, the shared model method retains an
exists?database fallback.
Putting the association-aware behavior in SecondFactorManager, rather than special-casing only the serializer, also lets other callers benefit whenever they have preloaded the same data. Existing site-setting checks and the distinction between second-factor security keys and first-factor passkeys remain intact.
Measured result
I benchmarked five runs locally in production mode with 75 active users and empty 2FA data.
| Metric | Before mean | After mean | Change |
|---|---|---|---|
| Server duration | 146.49 ms | 49.11 ms | −66.5% |
| SQL duration | 56.40 ms | 5.71 ms | −89.9% |
| Allocated objects | 61,292 | 27,292 | −55.5% |
| SQL events | 159 | 10 | −93.7% |
| Duplicate query fingerprints | 148 | 0 | −100% |
| User second-factor queries | 76 | 1 | −98.7% |
| Security-key queries | 75 | 1 | −98.7% |
| TOTP existence queries | 75 | 0 | −100% |
| Security-key existence queries | 75 | 0 | −100% |
The timing figures came from a local environment, but the deterministic query counts capture the direct improvement: 150 per-user existence checks became two association preload queries.
Validation
The request spec creates three representative users: one with TOTP, one with a second-factor security key, and one with a passkey. It confirms that the first two are reported as having 2FA enabled, preserves the existing response behavior for the passkey user, and asserts that the endpoint performs exactly one query for TOTP records and one for security keys.
The change was reviewed, approved, and merged into Discourse upstream.