Skip to main content
Mostafa Effati

About this platform

A working notebook for engineering practice

This is Mostafa Effati’s personal engineering platform: a place to turn hands-on work into clear writing, structured learning, and useful digital products.

Student collaborator

  • Ms Zahra Ehsani

    Former student · platform contributor

    Ms Zahra Ehsani worked on parts of this platform during her studies and brought thoughtful, practical contributions to its development. I'm glad to recognize her work here.

What you will find

  • Long-form articles, books, tutorials, and practical snippets.
  • Courses and guided learning paths built around real engineering work.
  • Case studies, open-source work, experiments, and product releases.

Built deliberately

  • A bilingual Persian and English experience with native RTL support.
  • Theme-aware, keyboard-friendly interfaces with a focused visual language.
  • Content and product changes developed as one versioned system.

The platform is continuously evolving. Some sections are complete products; others are active experiments that improve as the underlying work develops.

Frontend Session Edge

How a Next.js edge proxy keeps device and user-account cookies in sync — resolve device first, refresh account second, single-flight to avoid refresh races.
Mostafa Effati4 min readsoftware-architecture

The Frontend Must Respect Two Session Layers

Identity can issue perfect device and user-account tokens. If the web app treats them as one cookie jar, you undo the model at the edge.

In the Next.js app that consumes this BC, a request proxy owns session continuity on every matched navigation. Login UI still lives in React. Truth still lives in Identity. The edge’s job is ordering, refresh, and cookie hygiene.

Four cookies, two concerns

Cookie roleMeaning
Device accessShort-lived proof of known client (dsid)
Device refreshRotating secret for the device family
User accessShort-lived proof of logged-in account (uaid)
User refreshRotating secret for the account session family

HttpOnly, Secure, SameSite=lax. Expiry follows JWT exp so the browser and proxy agree on “stale.”

What the proxy does on each navigation

If device refresh fails, create a new device session. If user refresh fails or there is no valid device afterward, clear user cookies — do not limp along with a half-authenticated state.

Same-navigation visibility

Refreshing cookies only via Set-Cookie is not enough for Server Components in this request: they read the incoming Cookie header.

So the proxy rebuilds the upstream Cookie header with the new values (or deletions) before NextResponse.next. The browser still gets Set-Cookie for the next navigation. One round-trip, consistent view.

Single-flight against parallel refresh

HTML, RSC, and prefetch can all see an expired token at once. Without dedupe, each calls refresh → refresh-token reuse / race / extra latency.

In-process single-flight maps keyed by token identity: first caller works; others await the same Promise. That only covers one Node isolate. Multi-instance deploys still rely on Identity’s family rotation being correct; the edge only stops a stampede inside one process.

Route policy stays thin

Guest-only routes (for example password reset) redirect away when a user account session is alive. Logged-in gates redirect to login when it is not. Product home vs dashboard is a product choice — the session model should not care.

Some legacy product APIs may still use a separate compat cookie until convergence; the matcher can exclude those paths so the identity proxy does not fight them. That is migration reality, not a second architecture.

What not to put in the frontend

  • Provider client secrets
  • Password hashing
  • “Soft” session inventing a user id in localStorage
  • Refreshing user account before device

The edge is a careful client of Identity — not a miniature identity service.

Closing the book

Across nine chapters the arc is the same move, repeated:

SplitWhy
Person ≠ UserReality ≠ access
Contact ≠ columnsChannels have lifecycles
Citizenship ≠ attributeRelationships multiply
Device session ≠ account sessionClient ≠ login
Verify ≠ establishMethods converge
Org / geo ≠ free textContext is structured
Edge ≠ source of truthDelivery respects the model

Frameworks will change. If the domain splits stay honest, the next framework inherits a system that still matches the world.

Start again or dig in

Return to the book map or revisit Device vs User Sessions when debugging cookie order bugs.

Related documents

Command menu

↑ ↓to move · Enter to select · Esc to close
Navigation
Actions

Press Esc to close · ⌘K to toggle