Skip to content

[Bug]: Every server restart takes T3 Connect remote access down for 1–1.5 minutes: HTTP and the tunnel both wait for DB recovery, and the client backs off up to 5 minutes #24661

Open

Description

@matthias-scale

Summary

On a self-hosted t3 serve linked to T3 Connect, a restart (update, settings change, systemctl restart) cuts remote clients off for about 1–1.5 minutes plus the client's backoff. The process itself is down for only ~9 s. The rest is:

  1. every HTTP route waits on startup readiness, which comes only after V2 orchestration recovery, and recovery grows with the state DB;
  2. the managed cloudflared is a child of the server and is started only after that same recovery, so the tunnel is gone for the whole window (the relay answers 502);
  3. client backoff keeps growing during the window (cap 300 s), so after a ~90 s outage the next try is often 64–128 s away.

Version / setup

  • 0.1.3-nightly.20261023.3566, Linux x86_64, systemd user service via t3 __service-launcher. Same code on main at edb2b2f365.
  • T3 Connect managed tunnel (cloudflared 2025.x from PATH). Clients: macOS desktop nightly over the relay.
  • statev2.sqlite: 25–26 GB on host A, 16 GB on host B.

Numbers (server log, host A, n=4 restarts)

restart listening on :3773 V2 orchestration recovery completed relay client started listen → relay
10-23 14:52 14:52:53.9 14:53:54.4 14:53:55.8 62 s
10-23 15:53 (nightly update) 15:53:32.8 15:54:28.7 15:54:29.5 57 s
10-24 13:58 13:58:21.6 13:59:49.7 13:59:49.8 88 s
10-24 18:27 18:27:52.6 18:29:16.2 18:29:17.1 84 s
  • Stop → listen: ~9 s (10-24: stop 13:58:12, listen 13:58:21).
  • cloudflared registers 4/4 connections < 3 s after spawn, so almost all of the gap is server readiness, not Cloudflare.
  • Host B (16 GB DB): listen → relay 40 s (n=1).
  • What users see: ~1.6–3.7 min per restart including backoff.
  • Host A restarted 4 times in 7 days (updates, config-change restarts, manual).

Where in the code

Why an external connector alone does not fix it

A second cloudflared replica with the same token in its own service would save at most ~1.4 s. While the process is down the edge answers 502. During recovery the TCP connection is accepted but the request is held by the readiness middleware until the client's 15 s establishment timeout. Either way the client is in its retry loop with growing backoff. The fix has to be on the readiness path and the retry policy.

Asks (1 + 3 together fix most of it)

  1. Answer health and connect before recovery finishes. Accept the WebSocket and RPC ping at listen time and report a "starting / recovering" state, instead of holding every route on awaitCommandReady. The client stays connected and does not back off.
  2. Start the tunnel at listen time, not after recovery. Optionally support an external connector (a setting that skips spawning cloudflared, plus a way for a service manager to get the connector config).
  3. Short backoff on planned restarts. Before a planned shutdown (update, settings restart), tell clients "restarting, retry in N s", and reset or cap backoff while the relay answers 502/530 for a known-restarting environment.
  4. Optional: drain on SIGTERM with a restart close code, so the client can tell a planned restart from a network loss.

Related

Workarounds today

Fewer restarts (quiet windows), TUNNEL_TRANSPORT_PROTOCOL=http2, shrinking the state DB.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions