Skip to content

cold-start: decouple webhook registration from server hook#41

Merged
x0ba merged 1 commit into
stagingfrom
cold-start/decouple-webhook-hooks
May 28, 2026
Merged

cold-start: decouple webhook registration from server hook#41
x0ba merged 1 commit into
stagingfrom
cold-start/decouple-webhook-hooks

Conversation

@x0ba
Copy link
Copy Markdown
Owner

@x0ba x0ba commented May 28, 2026

Stack Context

This stack reduces Vercel cold-start time by shrinking the shared SvelteKit server boot path and isolating heavy agent/GitHub dependencies.

Why?

Every serverless invocation was loading GitHub webhook handler registration from hooks.server.ts, which pulled Octokit and regression scheduling into the global request path. Webhook handlers only need to exist for the webhook route, so registration is deferred until that route handles a request.

Test plan

  • Open /sign-in after a cold period and confirm faster first response
  • POST to /api/github/webhook and confirm handlers still fire for PR events

Webhook handlers now register lazily when the webhook route is hit, keeping Octokit and regression imports out of every cold boot.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flightlog Ready Ready Preview, Comment May 28, 2026 7:56am

Copy link
Copy Markdown
Owner Author

x0ba commented May 28, 2026

@x0ba x0ba changed the title Stop registering GitHub webhook handlers in the global server hook. cold-start: decouple webhook registration from server hook May 28, 2026
@x0ba x0ba marked this pull request as ready for review May 28, 2026 07:56
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Greptile Summary

This PR decouples GitHub webhook handler registration from the SvelteKit server hook, deferring it until the first request hits /api/github/webhook rather than running it on every cold start.

  • src/hooks.server.ts: Removes the eager registerGithubWebhookHandlers() call and its import, shrinking the global boot path for all routes.
  • src/lib/server/github/webhooks.ts: Introduces a module-level githubWebhookHandlersRegistered flag and an ensureGithubWebhookHandlersRegistered guard inside handleGithubWebhook; since getGithubApp() is already a singleton, the flag correctly tracks registration across warm requests within the same container.

Confidence Score: 4/5

Safe to merge — the lazy registration pattern is correct and the singleton App instance ensures handlers stay bound across warm requests.

The core logic is sound: getGithubApp() returns the same App instance per container lifetime, so the boolean flag accurately reflects whether handlers have been wired up. The one thing worth noting is that ensureGithubWebhookHandlersRegistered runs before signature verification, meaning any unauthenticated hit to the webhook endpoint on a fresh container will trigger handler registration — harmless today but an ordering inversion that could be surprising later.

The ordering of ensureGithubWebhookHandlersRegistered relative to signature verification in src/lib/server/github/webhooks.ts is worth a second look.

Important Files Changed

Filename Overview
src/hooks.server.ts Removes eager registerGithubWebhookHandlers() call and its import — clean, no issues.
src/lib/server/github/webhooks.ts Introduces lazy one-time handler registration via a module-level boolean flag; correct given the getGithubApp() singleton, but registration happens before signature verification on the first call.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Hooks as hooks.server.ts
    participant Route as webhook route
    participant Webhooks as webhooks.ts
    participant AppModule as app.ts

    Note over Hooks: Cold start (before PR)
    Hooks->>Webhooks: registerGithubWebhookHandlers()
    Webhooks->>AppModule: getGithubApp()
    AppModule-->>Webhooks: App singleton
    Webhooks-->>Hooks: handlers registered eagerly

    Note over Hooks: Cold start (after PR)
    Hooks-->>Client: no webhook import at boot

    Client->>Route: POST /api/github/webhook
    Route->>Webhooks: handleGithubWebhook(request)
    Webhooks->>AppModule: getGithubApp()
    AppModule-->>Webhooks: App singleton
    Webhooks->>Webhooks: ensureGithubWebhookHandlersRegistered flag false registers handlers
    Webhooks->>Webhooks: verify signature
    Webhooks->>Webhooks: webhooks.receive(event)
    Webhooks-->>Client: 200 ok

    Client->>Route: POST /api/github/webhook (warm)
    Route->>Webhooks: handleGithubWebhook(request)
    Webhooks->>Webhooks: ensureGithubWebhookHandlersRegistered flag true skips
    Webhooks->>Webhooks: verify and receive
    Webhooks-->>Client: 200 ok
Loading

Fix All in Cursor Fix All in Codex

Reviews (1): Last reviewed commit: "Stop registering GitHub webhook handlers..." | Re-trigger Greptile

return new Response('GitHub App is not configured', { status: 503 });
}

ensureGithubWebhookHandlersRegistered(githubApp);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Handler registration before signature verification

ensureGithubWebhookHandlersRegistered is called before the signature check, so any unauthenticated request to this endpoint on a fresh container will trigger handler registration. Functionally this is harmless — no events are dispatched until after webhooks.receive() — but the ordering is semantically inverted. Moving the call to just after signature verification aligns intent with execution.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Codex

Copy link
Copy Markdown
Owner Author

x0ba commented May 28, 2026

Merge activity

  • May 28, 4:49 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 28, 4:49 PM UTC: @x0ba merged this pull request with Graphite.

@x0ba x0ba merged commit e99ad36 into staging May 28, 2026
4 of 5 checks passed
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.

1 participant