Skip to content

fix(loader): skip Express session middleware on loader backends#192

Merged
jameswillis99 merged 1 commit intomasterfrom
fix/loader-session-middleware
Mar 20, 2026
Merged

fix(loader): skip Express session middleware on loader backends#192
jameswillis99 merged 1 commit intomasterfrom
fix/loader-session-middleware

Conversation

@jameswillis99
Copy link
Collaborator

The Express session middleware (express-session + passport.session()) was registered globally and fired on every request, including all loader endpoints (/api/v1/loader/, /static/js/loader-hydrate).

This caused two problems:

  1. Set-Cookie: connect.sid=... on CDN-cached responses. CloudFront/Fastly stores response headers on cache-miss and replays them on cache-hits. All users receiving a cached loader response were getting the session cookie from the original request. Versioned endpoints have a 1yr TTL, so this cookie was replayed for a very long time. The cookie is low-risk (empty anonymous session, no auth state), but is unintended pollution of public CDN responses.

  2. Unnecessary DB work per request. passport.session() calls deserializeUser() on every request, which issues a DB query to hydrate req.user. Loader routes authenticate exclusively via x-plasmic-api-project-tokens / x-plasmic-api-token headers (handled by apiAuth). They have zero references to req.session or req.user -- the DB lookup was pure waste on every loader request.

Fix: pass skipSession: true to createApp() in loader-backend.ts and loader-html-backend.ts. Both are dedicated backends that serve only loader routes. The skipSession path already exists in createApp() and is used by tests.

Studio (app-backend-real.ts) is unchanged -- it still needs session for login/logout and all authenticated Studio routes.

Closes plasmic-terraservices#11

The Express session middleware (express-session + passport.session()) was
registered globally and fired on every request, including all loader endpoints
(/api/v1/loader/*, /static/js/loader-hydrate*).

This caused two problems:

1. Set-Cookie: connect.sid=... on CDN-cached responses. CloudFront/Fastly
   stores response headers on cache-miss and replays them on cache-hits. All
   users receiving a cached loader response were getting the session cookie from
   the original request. Versioned endpoints have a 1yr TTL, so this cookie was
   replayed for a very long time. The cookie is low-risk (empty anonymous
   session, no auth state), but is unintended pollution of public CDN responses.

2. Unnecessary DB work per request. passport.session() calls deserializeUser()
   on every request, which issues a DB query to hydrate req.user. Loader routes
   authenticate exclusively via x-plasmic-api-project-tokens / x-plasmic-api-token
   headers (handled by apiAuth). They have zero references to req.session or
   req.user -- the DB lookup was pure waste on every loader request.

Fix: pass skipSession: true to createApp() in loader-backend.ts and
loader-html-backend.ts. Both are dedicated backends that serve only loader
routes. The skipSession path already exists in createApp() and is used by tests.

Studio (app-backend-real.ts) is unchanged -- it still needs session for
login/logout and all authenticated Studio routes.

Closes plasmic-terraservices#11
@jameswillis99 jameswillis99 merged commit b5a870f into master Mar 20, 2026
4 checks passed
@jameswillis99 jameswillis99 deleted the fix/loader-session-middleware branch March 20, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants