Skip to content

Answer or close keep-alive requests during NodeHttpServer shutdown - #8844

Open
mvanhorn wants to merge 1 commit into
Effect-TS:mainfrom
mvanhorn:fix/8728-node-http-server-keepalive-shutdown
Open

mvanhorn wants to merge 1 commit into
Effect-TS:mainfrom
mvanhorn:fix/8728-node-http-server-keepalive-shutdown

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Oct 6, 2026

Copy link
Copy Markdown

Type

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

server.close now starts once and completes a Deferred, so a timed-out waiter does not record the close as abandoned. Draining sets Connection: close on responses whose headers are still unsent and on requests that arrive after draining begins, and the request and upgrade listeners stay registered until that close effect finishes. When the graceful timeout elapses, closeAllConnections runs and the finalizer waits on the same Deferred. With disablePreemptiveShutdown, the timeout path is skipped and the server-scope finalizer closes the server, then removes the listeners.

While a Node HTTP server is shutting down, a further request on an already accepted keep-alive connection gets no response and hangs until the client times out. If the drain reaches gracefulShutdownTimeout, disposing the runtime fails with an interruption instead of finishing. The serve finalizer removed the request and upgrade listeners before server.close(), so Node still emitted request events for connections it was draining and nothing handled them. shutdown was Effect.cached, so the interruption from timeoutOrElse was stored as the close result, and the timeout branch was Effect.void, which left those sockets open.

Closes #8728

Related

server.close now starts once and completes a Deferred, so a timed-out
waiter does not record the close as abandoned. Draining sets Connection:
close on responses whose headers are still unsent and on requests that
arrive after draining begins, and the request and upgrade listeners stay
registered until that close effect finishes. When the graceful timeout
elapses, closeAllConnections runs and the finalizer waits on the same
Deferred. With disablePreemptiveShutdown, the timeout path is skipped
and the server-scope finalizer closes the server, then removes the
listeners.

Fixes Effect-TS#8728
@changeset-bot

changeset-bot Bot commented Oct 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bda9eab

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 32 packages
Name Type
@effect/platform-node Patch
effect Patch
@effect/opentelemetry Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-cloudflare Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/ai-typesafe Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-deno Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/docgen Patch
@effect/doctest Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-janitor effect-janitor Bot added the 4.0 label Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
arbitrary-combinators.ts 38.94 KB 38.94 KB 0.00 KB (0.00%)
basic.ts 7.06 KB 7.06 KB 0.00 KB (0.00%)
batching.ts 10.14 KB 10.14 KB 0.00 KB (0.00%)
brand.ts 6.73 KB 6.73 KB 0.00 KB (0.00%)
cache.ts 10.89 KB 10.89 KB 0.00 KB (0.00%)
config.ts 22.25 KB 22.25 KB 0.00 KB (0.00%)
differ.ts 21.34 KB 21.34 KB 0.00 KB (0.00%)
http-client.ts 22.44 KB 22.44 KB 0.00 KB (0.00%)
http-router.ts 33.95 KB 33.95 KB 0.00 KB (0.00%)
logger.ts 11.21 KB 11.21 KB 0.00 KB (0.00%)
metric.ts 9.03 KB 9.03 KB 0.00 KB (0.00%)
optic.ts 6.96 KB 6.96 KB 0.00 KB (0.00%)
pubsub.ts 15.18 KB 15.18 KB 0.00 KB (0.00%)
queue.ts 12.13 KB 12.13 KB 0.00 KB (0.00%)
schedule.ts 11.22 KB 11.22 KB 0.00 KB (0.00%)
schema-bigdecimal.ts 13.74 KB 13.74 KB 0.00 KB (0.00%)
schema-binary.ts 40.00 KB 40.00 KB 0.00 KB (0.00%)
schema-class.ts 21.07 KB 21.07 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 32.10 KB 32.10 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 27.28 KB 27.28 KB 0.00 KB (0.00%)
schema-string-transformation.ts 14.48 KB 14.48 KB 0.00 KB (0.00%)
schema-string.ts 12.00 KB 12.00 KB 0.00 KB (0.00%)
schema-template-literal.ts 16.07 KB 16.07 KB 0.00 KB (0.00%)
schema-toArbitrary.ts 38.46 KB 38.46 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 25.30 KB 25.30 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 20.26 KB 20.26 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 20.45 KB 20.45 KB 0.00 KB (0.00%)
schema-toFormatter.ts 20.57 KB 20.57 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 25.03 KB 25.03 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 20.55 KB 20.55 KB 0.00 KB (0.00%)
schema.ts 20.29 KB 20.29 KB 0.00 KB (0.00%)
stm.ts 13.23 KB 13.23 KB 0.00 KB (0.00%)
stream.ts 9.99 KB 9.99 KB 0.00 KB (0.00%)

This branch is waiting to be deployed

1 waiting deployment
fork — bda9eabd Waiting Oct 6, 2026 by mvanhorn via approval-gate #29703
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NodeHttpServer: requests on keep-alive connections hang during graceful shutdown

1 participant