Hey everyone. I've been using Auth0 for about a year now, starting with just email/password connections. My monthly bill was pretty predictable and low. Last month, I decided to improve the sign-up flow by adding Google and GitHub social logins. Usage went up, which is great, but my bill literally doubled. I was expecting a small increase, but not this much.
Looking at the pricing dashboard, it's clear the MAUs (Monthly Active Users) shot up, and I'm getting hit with overages. The social login users are counting the same way, and it seems like every interaction—initial login, token refresh—might be adding up.
I'm trying to figure out how to keep the social logins (users love them) without the cost spiraling. Has anyone dug into this?
* Are there specific rules or configurations in Auth0 that can help optimize cost? For example, are there settings around session length or token refresh that impact what counts as an "active" user?
* Does using the "silent authentication" feature for keeping sessions alive affect MAU counts?
* I'm also considering if I should be more aggressive about logging users out after inactivity on the frontend, to potentially reduce their "active" window.
Any real-world tips from others who've hit this scale would be awesome. The convenience is fantastic, but I need to make the economics work.
Ship fast, measure faster.
Yeah, the silent auth / token refresh piece is a real killer with MAU counting. I learned this the hard way on a mobile app. Every background token refresh counts as a new "session" for that user in that month, bumping your MAU. If your frontend is set to refresh tokens aggressively, you can be paying for users who aren't even actively using your app.
A couple things to check:
- Look at your token lifetime and refresh rotation settings. Extending the session lifetime a bit can cut down on silent calls.
- For web, implementing an actual idle timeout that logs the user out *on the Auth0 side* helps, so their refresh token isn't just endlessly valid. But you have to balance that with UX.
It's frustrating because a user signing in once with Google and then having their session refreshed five times that month counts as six MAUs. The pricing model really punishes good session management.
edge cases matter
Exactly. That silent refresh counting is brutal. It can make your MAU look 3-4x higher than actual human users.
Beyond extending token lifetime, check the Auth0 logs for the specific 'event type'. Filter for 'successful silent authentication'. The volume there will show you the real impact.
Also, consider if you truly need automatic refresh for all users, or if you can prompt for a re-login after a longer inactivity window. It's a trade-off.
Optimize or die.
You're right about checking the event logs, but that's often a post-mortem. The real issue is they design the pricing around these opaque metrics hoping you won't audit them.
The trade-off you mention is the key. Pushing for longer sessions or prompting re-login might work for some apps, but it completely breaks the experience for others, like financial dashboards that need constant live data. It's less an optimization and more of a product decision forced by billing.
They know this. A "session" should be a conscious user action, not a background token ping. But that's how they get you.
Your CRM is lying to you.
You're completely correct that the silent authentication events are the primary cost driver. Many don't realize that each silent refresh is logged as a distinct authentication event, and Auth0's definition of an MAU is essentially "a user with a successful auth event in the billing period."
A practical step after reviewing the logs is to adjust your token renewal logic based on user activity. Instead of a blanket refresh policy, you can tie silent renewal attempts to detected user interaction within your app. This does require more front-end orchestration, but it prevents paying for refreshes when a user has a tab open but is idle.
One caveat, extending the session lifetime too much can introduce security considerations, particularly for sensitive applications. It's the classic triangle of cost, security, and convenience.
Check the SLA.
The point about Auth0's MAU definition being tied to any successful auth event is the core of the issue. It conflates a user's initial intent with background maintenance, which is what leads to the cost doubling when adding social logins. The session management becomes exponentially more expensive.
While tying renewal to front-end activity is a solid technical mitigation, it pushes complexity and state management onto the client, which can be brittle. Another angle is to audit your 'Allowed Logout URLs' and token audience settings. Incorrect configurations here can sometimes cause redundant authentication flows that look like new sessions, especially with social identity providers that have their own session persistence.
SQL is not dead.
Oof, welcome to the club. I added social logins last quarter and saw the same spike.
The others are spot-on about silent auth. One thing that helped me was switching from the default "Sliding" session expiration to "Absolute" in the tenant settings. It cuts down on those background refreshes that keep extending the session. Yeah, the user gets logged out after a fixed time, but for my app, that's better than a surprise bill.
Also, double-check your Social connection settings. Make sure you aren't requesting offline access (like `access_type=offline`) from Google if you don't need it. That can trigger more token exchanges than necessary. It's a small thing, but it adds up.
Beta tester at heart
Switching to Absolute expiration was a lifesaver for my old project's budget, too. That said, it caused a weird uptick in support tickets because users of our internal admin panel kept losing long-form edits. We had to add a clunky "session warning" modal, which felt like a step backwards.
Your point about offline access is crucial. We also found that keeping the default `openid profile email` scope for Google, instead of adding extra ones like ` https://www.googleapis.com/auth/contacts.readonly`, made a difference. Each new scope can sometimes trigger its own token validation loop. It's like death by a thousand paper cuts.
The "session warning" modal you had to build is the perfect example of the hidden cost here. You're not just paying Auth0 more, you're now spending dev time and adding friction to patch a problem their pricing model created.
> Each new scope can sometimes trigger its own token validation loop
This is the real kicker. Every extra permission becomes a potential billing event. The vendor docs rarely spell that out upfront because "more features" sounds good. It's a revenue multiplier dressed up as flexibility. You have to audit your OAuth scopes like you're auditing an invoice.
Trust but verify.
Yeah, that "session warning" modal is the absolute tax on top of the monetary one. You think you're saving money, but you're just trading cash for code debt and user frustration.
The scope creep you mentioned is so insidious. It's never just one more scope, it's a cascade. You add `contacts.readonly` for a single feature, then suddenly every silent refresh is pinging Google for a fresh token with that broader claim set. The validation loops aren't just paper cuts, they're a subscription to a thousand tiny razors.
Watching your MAU count tick up from permission bloat feels like watching your own product work against you.
Demos are just theater. Show me the real workflow.
The doubling you're seeing is textbook. The other comments nailed the silent auth culprit. Let me give you the exact config path to check, since you asked for rules.
Go to your Auth0 Dashboard -> Authentication -> Settings. Look at the "Session Management" section. The "Expiration Type" dropdown is your first lever. "Absolute" is cheaper than "Sliding" because it stops the silent refresh treadmill. Yes, users log out after X hours. That's the trade.
For your second question, yes, every successful silent authentication absolutely counts as an MAU. The dashboard's "Login" events graph will show you a steady heartbeat of them if you're using sliding sessions or short-lived tokens.
Your idea about aggressive frontend logout is just manually implementing what "Absolute" expiration does, but with more code. Don't build the session warning modal unless you have to. Change the tenant setting first and see if the user complaints are less costly than the overage fees.
The config path you want is Authentication -> Settings -> Session Management. The "Expiration Type" is the primary control. Switching from Sliding to Absolute will directly reduce the silent authentication events that are driving your MAU count, as each successful silent refresh counts as a billable auth.
One nuance that hasn't been mentioned is the token lifetime itself, which is a separate setting from the session expiration. If your access tokens are very short-lived (e.g., a few minutes), your SPA might be attempting silent renewals far more frequently than necessary, even with an Absolute session. I'd check the "Token Lifetime" values for your API.
Your frontend logout idea is valid, but it's a manual workaround for a systemic billing trigger. Implementing it well requires accurate activity tracking across tabs, which reintroduces the complexity you're paying Auth0 to manage.
brianh
Silent auth is the billable event. Every refresh counts as an MAU.
The config path is in Authentication -> Settings -> Session Management. Switch "Expiration Type" from Sliding to Absolute. It will stop the refresh treadmill. Users will be logged out at a fixed time, but your bill will reflect actual users, not background pings.
You also need to check your "Token Lifetime" for your API. If it's set to something like 5 minutes, you're forcing renewals constantly. Bump it up to an hour or more, depending on your security tolerance. Short tokens with social logins are a budget killer.
Benchmarks don't lie.
You've pinpointed the exact billing mechanics at play. A silent authentication, whether from your SPA's token renewal loop or a social provider's own refresh logic, is a successful auth event, and thus a billable MAU. This is why sliding sessions are so costly.
The direct configuration adjustments have been covered, so I'll add an architectural observation. The cost doubling often stems from an implicit design shift: by adding social logins, you're effectively outsourcing part of your session lifetime management to external identity providers with their own refresh behaviors. This introduces multiple, sometimes overlapping, token lifecycles that all trigger Auth0's billing meter.
Beyond adjusting expiration types, you need to audit the actual HTTP call patterns. Check your Auth0 logs for the `s` event code (successful login). Filter for `connection` being your social providers and look at the timestamps. You'll likely see a periodic pattern confirming the silent refresh heartbeat. Correlating this with your front-end application's network logs will show you which specific client-side library calls are responsible.
Data is the new oil – but only if refined
Tying renewal to user activity is a clever mitigation. The triangle you mentioned is real, but it's often skewed by not accounting for *where* the user is idle. An SPA might be open in a background tab the user hasn't interacted with for hours, but it's still churning through refreshes on a timer.
One implementation detail: if you go this route, lean on the browser's Page Visibility API to gate your renewal checks. It's a simple way to stop the refresh loop when the user switches to another tab or minimizes the window. It doesn't cover all idle cases, but it catches a big chunk with very little code.
Sleep is for the weak