Why You Get Logged Out After an Hour
In this article
If you've been logged out of your account in the middle of a work session with no warning, the explanation is simple and by design: the session token issued when you log in is only valid for one hour, full stop, and nothing in the system silently extends it while you're active. This piece covers exactly what that token is, why an hour was chosen as a hard boundary rather than a rolling one, and the separate, more tightly scoped token used for the brief window during a two-factor login.
What the Session Token Actually Is
Signing in successfully issues a JSON Web Token — a signed, self-contained credential containing your user ID and email, cryptographically signed with a server-held secret so it can't be forged or altered by the client holding it. That token is what your browser sends with every subsequent request to prove who you are; the server doesn't keep a separate record of "logged in" sessions to check against; it just verifies the token's signature and reads its expiry claim on each request. The token itself carries an expiresIn claim set to exactly one hour from the moment it was issued, baked in at signing time.
There's No Refresh Token Behind the Scenes
Some systems pair a short-lived access token with a longer-lived refresh token that quietly exchanges for a new access token in the background, so a user never notices their original token expiring. That pattern doesn't exist here. There is exactly one token, it's valid for one hour from issuance, and when it expires the authentication middleware rejects the request with a specific "Token expired. Please log in again." message rather than silently minting a replacement. Whatever you were doing gets interrupted, and the fix is the same every time: sign in again, which issues a fresh token with a fresh one-hour clock.
Why the Expiry Is a Hard Wall, Not a Rolling Window
Because the expiry is a timestamp baked into the token at the moment you logged in, it doesn't reset just because you kept using the product. Ninety minutes of continuous, active work still ends in a forced logout thirty minutes before you stopped — the token doesn't know or care that you're still there clicking around; it only knows what time it was created. This is a meaningfully stricter model than a "sliding" session that extends every time you make a request, and it means the one-hour figure is really closer to "you'll never stay signed in longer than an hour without re-authenticating," not "you'll be logged out after an hour of inactivity."
The Two-Factor Login Flow Uses a Separate, Weaker Token — Deliberately
If you have two-factor authentication enabled, a correct password alone doesn't get you a full session token. It gets you a short-lived temporary token — valid for five minutes, not one hour — carrying a purpose claim that marks it as usable for exactly one thing: submitting your six-digit code or a backup code to the second-factor verification endpoint. The authentication middleware that guards every other protected route explicitly checks for that purpose claim and rejects any token carrying one, even though it's signed with the same server secret and would otherwise pass signature verification cleanly. That check exists specifically so a correct password by itself — without the second factor — can never be exchanged for real account access, even by someone who intercepted the temporary token in transit or figured out how JWTs work. Only after the second factor is verified does the server issue an actual one-hour session token, identical in shape and lifetime to the one issued on a non-2FA login.
What This Means in Practice
The practical upshot is that there's no setting to extend your session, no "remember me" option that keeps a token alive longer, and no background refresh quietly buying you extra time. If you're working through something that's likely to take more than an hour — a long CSV import review, filling out a big batch of invoices — it's worth expecting the occasional forced re-login as a normal part of the workflow rather than a bug, and saving your work incrementally rather than assuming a single unbroken hour-plus session is guaranteed.
Related Articles
How an Invoice Is Stored: One Row per Line Item, Plus a Full Copy
A saved invoice is stored as one database row per line item, linked by a shared group ID, with a full copy of the invoice on every row. Saving an edit replaces all of those rows in one transaction.
Why Sign-In Attempts Are Rate Limited
Sign-in, sign-up, two-factor checks, and verification resends share a budget of 10 attempts per hour per IP address, which is much stricter than the limit on ordinary app requests. Here's why the numbers differ.
How Sign-Up and Email Verification Actually Work
Creating an account sets up a personal workspace in the same database transaction, the verification link lasts 24 hours, and clicking an expired one quietly sends you a fresh link instead of leaving you stuck.
How Your Logo Gets Stored When You Upload It
A logo pasted in as a remote URL gets fetched server-side, checked against a 2MB cap and a real image content type, and converted into a self-contained data URL before it's saved.
How Client Portal Links Expire
A portal link defaults to 30 days, checks expiry on every request rather than up front, and matches a client's documents by an exact, case-sensitive-safe comparison — not a database foreign key.
How Invoice View Tracking Actually Works
Two separate mechanisms record when a client opens your invoice — a running counter and a detailed event log — and a password-protected share link doesn't count as viewed until the password is entered.