Cut what a signed-in tab costs by two thirds

Two changes on the push path, both measured against a real Stalwart 0.16.20
with the container capped at 256 MiB and tabs added in steps of 200 until the
kernel killed it:

                                  tabs held   per tab   of which native
  before                              1,665   133 KiB          81 KiB
  pin upstream calls to STALWART_URL  3,400    58 KiB           8 KiB
  + raw push relay                    4,979    37 KiB          10 KiB

Stalwart advertises absolute https URLs in every session, and the proxy
followed them -- so even with STALWART_URL naming a private plain-HTTP hop on
the same Docker network, every held push stream went out through TLS. That leg
is about 80 KiB of OpenSSL state per tab: native memory Node cannot see, which
is why neither the heap ceiling nor the stream buffer size ever moved the
number. absoluteUpstream() now keeps the path and query from the advertised
URL and the scheme, host and port from the configured one. A setup that must
reach Stalwart at an origin other than the one it was given sets
STALWART_FOLLOW_ADVERTISED_URLS=1.

With the transport out of the way, the fetch()-based relay was the next cost:
an undici Response, a web ReadableStream, a reader and Hono's stream bridge
held alive per tab, about 44 KiB of heap for a session that otherwise costs
4 KiB. relayPushRaw() pipes the upstream socket into the Node response and
tells the adapter the response is already sent. RAW_PUSH_RELAY=0 restores the
fetch path for comparison.

JMAP throughput is unchanged (2,383/s against 2,484/s at 50 users, inside
run-to-run noise); the relay does not touch that path. Verified that a push
stream through the raw relay delivers a StateChange while mail is written.

The install page's advice to set --max-old-space-size was measured in the same
runs and made no difference at all -- 3,400 tabs with it and without -- and
is withdrawn in the docs alongside this change.
This commit is contained in:
2026-09-06 00:42:19 -07:00
parent 5356e603fe
commit 01f721d8d1
4 changed files with 97 additions and 1 deletions
+4
View File
@@ -298,6 +298,10 @@ export const config = {
cookieName: env("COOKIE_NAME", "ihm_session"),
staticDir: process.env.STATIC_DIR ?? fileURLToPath(new URL("../../web/dist", import.meta.url)),
loginRateLimit: int("LOGIN_RATE_LIMIT", 10),
/* See relayPushRaw(): pipe the push stream socket-to-socket instead of through fetch(). */
rawPushRelay: process.env.RAW_PUSH_RELAY !== "0",
/* See absoluteUpstream(): follow Stalwart's advertised origin instead of pinning to ours. */
followAdvertisedUrls: process.env.STALWART_FOLLOW_ADVERTISED_URLS === "1",
};
export type Config = typeof config;