<@ULVA73B9P> Jul 09 11:32:57 Prefect prefect[4251]: 11:32:57.838 | DEBUG | uvicorn.error - % sendi...
s
@Marvin Jul 09 113257 Prefect prefect[4251]: 113257.838 | DEBUG | uvicorn.error - % sending keepalive ping Jul 09 113257 Prefect prefect[4251]: 113257.840 | DEBUG | uvicorn.error - > PING 04 eb 9e 7d [binary, 4 bytes] Jul 09 113257 Prefect prefect[4251]: 113257.841 | DEBUG | uvicorn.error - % sending keepalive ping Jul 09 113257 Prefect prefect[4251]: 113257.842 | DEBUG | uvicorn.error - > PING 34 01 73 98 [binary, 4 bytes] Jul 09 113257 Prefect prefect[4251]: 113257.844 | DEBUG | uvicorn.error - < PONG 04 eb 9e 7d [binary, 4 bytes] Jul 09 113257 Prefect prefect[4251]: 113257.845 | DEBUG | uvicorn.error - % received keepalive pong Jul 09 113257 Prefect prefect[4251]: 113257.846 | DEBUG | uvicorn.error - < PONG 34 01 73 98 [binary, 4 bytes] Jul 09 113257 Prefect prefect[4251]: 113257.847 | DEBUG | uvicorn.error - % received keepalive pong Jul 09 113259 Prefect prefect[4251]: 113259.480 | DEBUG | uvicorn.error - < PING 07 6b 3c 84 [binary, 4 bytes] Jul 09 113259 Prefect prefect[4251]: 113259.482 | DEBUG | uvicorn.error - > PONG 07 6b 3c 84 [binary, 4 bytes] Jul 09 113304 Prefect prefect[4251]: 113304.950 | DEBUG | uvicorn.error - < PING a6 41 82 c0 [binary, 4 bytes] Jul 09 113304 Prefect prefect[4251]: 113304.952 | DEBUG | uvicorn.error - > PONG a6 41 82 c0 [binary, 4 bytes] ui/api takes time to respond in between intervals, my config root@Prefect:/home/prefect# cat /etc/systemd/system/prefect-server.service [Unit] Description=Prefect Server After=network-online.target postgresql.service Wants=network-online.target [Service] Type=simple User=root WorkingDirectory=/home/prefect Environment="PREFECT_HOME=/home/prefect/.prefect" Environment="PREFECT_SERVER_API_HOST=192.168.29.151" Environment="PREFECT_SERVER_API_PORT=4200" Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60" Environment="PREFECT_SERVER_LOGGING_LEVEL=DEBUG" Environment="PREFECT_API_DATABASE_CONNECTION_URL=postgresql+asyncpg://prefect:prefectpassword@127.0.0.1:5432/prefect" Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxxx" ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200 --keep-alive-timeout 60 Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target root@Prefect:/home/prefect#
m
thought for 85.9 seconds
Those
PING
/
PONG
lines are normal. They’re just uvicorn/websocket keepalive messages, not the cause by themselves. What they mean: - the UI has an open WebSocket to the API - the server sends a ping - the browser/client responds with a pong - this keeps the connection alive So the main issue is likely server/API responsiveness, not the ping logs. A few things stand out in your config: 1. You are running with
DEBUG
logging
-
PREFECT_SERVER_LOGGING_LEVEL=DEBUG
- This can create a lot of noise and some overhead - First step: switch to
INFO
2. Your DB env var looks malformed in the pasted config - You showed:
Copy code
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:prefectpassword@127.0.0.1:5432/prefect>"
- If those
<
and
>
are literally in the service file, that is wrong - It should be:
Copy code
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:prefectpassword@127.0.0.1:5432/prefect>"
3.
PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60
is HTTP keepalive-related
- It is not the websocket ping interval you are seeing - It usually won’t fix intermittent UI slowness What I’d recommend first: Update your systemd service like this:
Copy code
ini
[Unit]
Description=Prefect Server
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/prefect
Environment="PREFECT_HOME=/home/prefect/.prefect"
Environment="PREFECT_SERVER_API_HOST=192.168.29.151"
Environment="PREFECT_SERVER_API_PORT=4200"
Environment="PREFECT_SERVER_LOGGING_LEVEL=INFO"
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:prefectpassword@127.0.0.1:5432/prefect>"
Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxxx"

ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200

Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
Then reload and restart:
Copy code
bash
sudo systemctl daemon-reload
sudo systemctl restart prefect-server
sudo journalctl -u prefect-server -f
Next checks: 1. Test API health directly
Copy code
bash
curl -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If that is fast consistently, the backend is mostly OK and the slowdown may be on specific UI queries. 2. Watch for real errors in logs Look for: - database timeout errors - connection pool errors - postgres errors - long request times 3. Check PostgreSQL performance Since you’re self-hosting, intermittent slowness is often DB-related: - slow queries - connection pool saturation - disk I/O / CPU pressure Useful checks:
Copy code
bash
top
free -h
df -h
sudo -u postgres psql -c "select now();"
4. Reduce log verbosity If you don’t need wire-level logs,
INFO
is better than
DEBUG
. A couple more notes: - The ping/pong messages are expected for the live UI connection. - If the UI “hangs” while API health is fast, the problem may be a heavy API endpoint or browser/network issue. - If all API requests are slow, focus on PostgreSQL and server resources first. Relevant docs: - Prefect docs - Self-hosting Prefect - Settings and profiles If you want, send: - output of
curl -u ... /api/health
-
journalctl -u prefect-server -n 100
- whether the slowness is on all pages or only flow runs / task runs / logs and I can help narrow it down.
s
@Marvin i don't think its performance issue, when my server remains idle from other network when i try to make api call to server its getting failed on first few calls
m
thought for 96.9 seconds
That does not sound like Prefect “going idle” internally. Prefect server does not have a sleep/wake behavior where it stops serving requests after inactivity. If the first few requests fail after idle, then later requests succeed, that usually points to a network/proxy/connection reuse issue rather than Prefect application logic. Most likely causes: 1. A stale idle TCP connection is being reused This is the most common pattern: - client or proxy keeps an HTTP connection open - server/proxy/NAT/firewall drops it during idle time - first request tries to reuse the dead connection and fails - next request opens a fresh connection and succeeds That exactly matches “first few calls fail, then OK”. 2. Reverse proxy / load balancer / firewall idle timeout mismatch If you have any of these in front of Prefect: - nginx - Apache - HAProxy - cloud load balancer - VPN / NAT / firewall appliance they may be dropping idle connections before the client realizes it. 3. Client-side connection pooling If your caller is using
requests
,
httpx
, browser keepalive, or another pooled HTTP client, the first call may hit a dead pooled connection. Important point: - the
PING/PONG
logs you pasted are WebSocket keepalives for the UI - your failing API calls are likely plain HTTP, not websocket - so those logs are probably just a symptom of an open UI session, not the cause What I would check next: 1. Is there a proxy in front of Prefect? Are clients calling: - directly:
<http://192.168.29.151:4200>
- or through nginx / domain / VPN / LB? If there is a proxy, this becomes the top suspect. 2. Test from another machine with fresh one-off curl calls Run this after the server has been idle:
Copy code
bash
curl -v -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
curl -v -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
curl -v -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If the first fails and the next ones succeed, please capture the exact error: - connection refused - connection reset by peer - empty reply from server - timeout - 401/403 - TLS/SSL error That error text matters a lot. 3. Force no connection reuse in the test Try:
Copy code
bash
curl -v -H "Connection: close" -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If
Connection: close
makes the issue disappear, that strongly suggests stale keepalive connection reuse. 4. Check if this only happens cross-network You mentioned “from other network”. That suggests: - NAT timeout - firewall session timeout - VPN idle timeout - proxy idle timeout If local calls from the same host always work, but remote calls after idle fail, the problem is probably between the client and the server, not in Prefect itself. About your current setting:
Copy code
ini
Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60"
That affects uvicorn HTTP keepalive behavior, but it may not solve the issue if: - a proxy/firewall kills idle sessions earlier - the client is reusing dead pooled sockets - some middlebox has a shorter timeout Still, 60 is reasonable. The key is that all layers need compatible timeout behavior. My practical recommendation: Temporarily simplify the path 1. call Prefect directly by IP and port from the remote client 2. avoid any proxy/domain if possible 3. use
curl -v
with
Connection: close
4. compare behavior If direct-IP works reliably but proxied/domain access fails after idle, the proxy/network layer is the problem. Also, switch logs to
INFO
unless you need packet-level debug:
Copy code
ini
Environment="PREFECT_SERVER_LOGGING_LEVEL=INFO"
If you want, send me: - the exact failing curl error output - whether you use nginx / LB / VPN / firewall in front of Prefect - whether
Connection: close
changes the behavior and I can narrow it down very quickly.
s
@Marvin we are calling ui/api directly
<http://192.168.29.151:4200> and after idl first error our first request gets timedout. we are not using any proxy client is my laptop and server is locally in same network
m
thought for 14.7 seconds
Got it — if you're calling
<http://192.168.29.151:4200>
directly, with no proxy, and the first request after idle times out, then this is much less likely to be a Prefect-specific setting and more likely one of: - ARP / neighbor cache resolution delay on the LAN - host firewall / conntrack / NIC power-saving - server process briefly not accepting or not responding on first new connection - less commonly, client connection reuse if you’re using a browser/app session instead of one-off requests Also: if the browser UI is what times out first after idle, browsers do aggressively reuse connections. Important: Prefect server itself should not “sleep” after idle. What to test next 1. Compare browser vs fresh curl After the server has been idle, from your laptop run:
Copy code
bash
curl -v --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
Then immediately again:
Copy code
bash
curl -v --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
And also:
Copy code
bash
curl -v --connect-timeout 5 -H "Connection: close" -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
What matters is whether the timeout happens during: - TCP connect - sending request - waiting for response If
Connection: close
helps, that points to stale keepalive reuse. 2. Test from the server itself when idle On the server:
Copy code
bash
curl -v --connect-timeout 5 -u astra:xxxxxxxx <http://127.0.0.1:4200/api/health>
If localhost is always fast, but laptop-to-server first request times out, then the problem is definitely network/LAN/firewall/NIC, not Prefect app logic. 3. Check whether the TCP port is listening continuously On the server:
Copy code
bash
ss -ltnp | grep 4200
You should see Prefect/uvicorn listening on
0.0.0.0:4200
or similar. 4. Watch packets during the first failed request On the server, before reproducing:
Copy code
bash
sudo tcpdump -i any host 192.168.29.151 and port 4200
Then make the first request from your laptop after idle. This tells you whether: - the SYN reaches the server - the server replies - the request reaches uvicorn - the response is delayed or absent 5. Check server logs exactly at first timeout Run:
Copy code
bash
sudo journalctl -u prefect-server -f
Then reproduce the idle timeout and see whether Prefect logs anything at all for that first request. Interpretation: - No log entry at all → request is not reaching the app cleanly; network/socket layer issue - Log entry appears late → app accepted it but responded slowly - Immediate auth/error log → app received it, not a network issue A few strong clues here Since: - same LAN - direct IP - no proxy - failure only after idle - later calls succeed I would suspect LAN/NIC/firewall behavior before Prefect. Common examples: - Linux power-saving on NIC - firewall state table timeout - ARP resolution delay - Wi-Fi sleep behavior on laptop - security software on either machine Things worth checking on the server Firewall If
ufw
or iptables/nftables is active:
Copy code
bash
sudo ufw status
sudo iptables -L -n
sudo nft list ruleset
ARP/neigh table After idle, before first request and after first request:
Copy code
bash
ip neigh
If the entry for your laptop/server is stale/delayed, first contact can pause. NIC power management If server is on Wi-Fi or certain virtualized NICs, idle wakeup can delay traffic. Server resource sanity Even if this doesn’t feel like performance, still check there isn’t a pause:
Copy code
bash
top
vmstat 1
dmesg -T | tail -n 50
Especially look for: - NIC resets - kernel network warnings - OOM or CPU stall messages One very useful isolation test From your laptop, after idle:
Copy code
bash
ping 192.168.29.151
Then immediately:
Copy code
bash
curl -v --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If ping first makes the API request succeed, that strongly suggests ARP/NIC/network-idle behavior, not Prefect. You can also test:
Copy code
bash
nc -vz 192.168.29.151 4200
after idle, before curl. My current best guess Based on what you’ve shared, my ranking is: 1. network idle / ARP / NIC issue on LAN 2. browser/client reusing stale HTTP connection 3. host firewall / conntrack timeout behavior 4. Prefect/uvicorn issue — possible, but less likely Docs: - Self-hosting Prefect - Settings and profiles If you want, send me the outputs of these 3 tests:
Copy code
bash
curl -v --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
curl -v --connect-timeout 5 -H "Connection: close" -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
ping 192.168.29.151
right after an idle period, and I can tell you which layer is failing.
s
@Marvin after 1 api call i see this packets root@Prefect:/home/prefect# sudo tcpdump -i any host 192.168.29.87 and port 4200 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 120725.407194 enp0s3 In IP 192.168.29.87.62116 > Prefect.4200: Flags [.], seq 3010554287:3010554288, ack 2464962840, win 255, length 1 120725.407229 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62116: Flags [.], ack 1, win 501, options [nop,nop,sack 1 {0:1}], length 0 120726.411162 enp0s3 In IP 192.168.29.87.62116 > Prefect.4200: Flags [.], seq 0:1, ack 1, win 255, length 1 120726.411190 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62116: Flags [.], ack 1, win 501, options [nop,nop,sack 1 {0:1}], length 0 120727.424573 enp0s3 In IP 192.168.29.87.62116 > Prefect.4200: Flags [.], seq 0:1, ack 1, win 255, length 1 120727.424639 enp0s3 Out IP Prefect.4200 > such for next 60 seconds
m
thought for 13.9 seconds
This is a very useful clue. What your
tcpdump
shows is not a new HTTP request. It shows an already-established TCP connection sending tiny packets repeatedly, and the server is ACKing them. That usually means the client is trying to use an existing idle connection, not opening a fresh one. Key signs from your capture: - no TCP
SYN
packet - no new handshake - just packets on an existing connection:
192.168.29.87.62116 > Prefect.4200
- server replies with ACKs - repeats for a long time So the likely situation is: 1. your laptop/browser/client has an old keepalive connection open to
:4200
2. after idle, the first request tries to reuse that connection 3. something in the HTTP exchange gets stuck or delayed 4. eventually a fresh connection gets created and things work again This points more toward HTTP keepalive / stale connection reuse than ARP or server sleep. What I’d do next 1. Capture full packets, not just summary Run this on the server:
Copy code
bash
sudo tcpdump -i any -nnvvXSs 0 host 192.168.29.87 and port 4200
Then make exactly one first request after idle. This will show whether the client is sending: - partial HTTP headers - chunked data - websocket frames - TCP zero-window / retransmits / FIN/RST 2. Force a brand-new connection from laptop After idle, do:
Copy code
bash
curl -v --http1.1 -H "Connection: close" --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If this succeeds immediately while the browser/UI first call hangs, then the issue is almost certainly stale persistent connection reuse in the browser/client. 3. Compare with browser devtools Open browser devtools -> Network tab, then after idle reload the UI or call the API. Look at the first failed request: - is it marked
stalled
? -
pending
? -
waiting for server response
? -
connection start
issue? - does it reuse an existing connection? That will help confirm whether the browser is trying to reuse a bad socket. 4. Lower or disable keepalive as a test Since this seems connection-reuse related, test with a shorter keepalive or with connection close behavior at the client side. You already have:
Copy code
ini
Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60"
For testing, I would actually try lowering it back down or removing it, then restarting, because a longer keepalive can preserve bad idle connections longer in some environments. Try:
Copy code
ini
Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=5"
then:
Copy code
bash
sudo systemctl daemon-reload
sudo systemctl restart prefect-server
This is not because 5 is universally better, but because it helps test whether long-lived idle sockets are the problem. 5. Test with no browser, only curl If plain
curl
with
Connection: close
works every time after idle, but browser/UI still hangs on first request, then Prefect is probably fine and the issue is specifically browser persistent connection behavior. What your capture does not suggest - not an app process crash - not Prefect “sleeping” - not a missing listener on port 4200 - not basic connectivity loss Because the server is actively ACKing traffic on that connection. Most likely diagnosis now Based on this packet capture, my best guess is: the first request after idle is being sent over an old persistent HTTP connection that is in a bad state Possible reasons: - browser/client pooled socket reuse - weird half-open TCP state - auth/UI session trying to reuse old connection - less likely a uvicorn/http parser edge case on reused idle sockets Strongest confirming test Please run this after idle from the laptop:
Copy code
bash
curl -v --http1.1 -H "Connection: close" --connect-timeout 5 -u astra:xxxxxxxx <http://192.168.29.151:4200/api/health>
If that works immediately, while the browser still times out on first try, we’ve basically isolated it to persistent connection reuse. If you want, I can also help you do a cleaner
tcpdump
interpretation if you send:
- output of
curl -v --http1.1 -H "Connection: close" ...
- browser Network tab screenshot/error text - result of:
Copy code
bash
sudo tcpdump -i any -nnvvXSs 0 host 192.168.29.87 and port 4200
One more small note: if you only use this internally, switching the browser test to a private/incognito window can also help eliminate reused connection/session effects.
s
@Marvin this are from my frontend in nextjs api call to server root@Prefect:/home/prefect# sudo tcpdump -i any host 192.168.29.87 and port 4200 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 121053.048703 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [S], seq 4170125526, win 65535, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0 121053.048788 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62662: Flags [S.], seq 248243941, ack 4170125527, win 64240, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0 121053.050716 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [.], ack 1, win 255, length 0 121053.051668 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [P.], seq 1:495, ack 1, win 255, length 494 121053.051708 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62662: Flags [.], ack 495, win 501, length 0 121053.354023 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62662: Flags [P.], seq 1:175, ack 495, win 501, length 174 121053.354574 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62662: Flags [P.], seq 175:6446, ack 495, win 501, length 6271 121053.357344 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [.], ack 6446, win 255, length 0 121057.359511 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [F.], seq 495, ack 6446, win 255, length 0 121057.360160 enp0s3 Out IP Prefect.4200 > 192.168.29.87.62662: Flags [F.], seq 6446, ack 496, win 501, length 0 121057.361886 enp0s3 In IP 192.168.29.87.62662 > Prefect.4200: Flags [.], ack 6447, win 255, length 0 121116.639478 enp0s3 In IP 192.168.29.87.50429 > Prefect.4200: Flags [S], seq 73365197, win 65535, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
m
thought for 14.7 seconds
This capture is very telling. In this case, Prefect is responding normally to the Next.js request. What happened in your trace: 1. client opens a new TCP connection -
S
/
S.
/
.
= normal TCP handshake 2. client sends request data -
Flags [P.] ... length 494
3. server ACKs it 4. server sends response data back - one packet
length 174
- another packet
length 6271
5. client ACKs the response 6. 4 seconds later the client closes the connection - client sends
F.
- server closes too That means: - the request reached Prefect - Prefect processed it - Prefect sent a response - the client received the response packets - then the client side closed the connection So for this captured request, the timeout is not on the Prefect server side. That shifts the likely problem toward your Next.js/frontend side: - the frontend may be waiting on response parsing - the frontend may be timing out before consuming the response correctly - the frontend may be making a request that succeeds at TCP/HTTP level but your app logic treats as failed - or the browser/Next.js layer is doing multiple requests and only one is succeeding Most important observation: there is no network stall in this trace. The server replies within about `~300 ms`: - request at
12:10:53.051668
- response starts at
12:10:53.354023
That is healthy. So now I would focus on what your Next.js code is doing with the response. Things to check in Next.js 1. Are you calling Prefect from server-side Next.js code or browser code? - server-side route handler / API route - client-side fetch in browser - middleware - SSR / RSC fetch This matters because timeouts and connection reuse differ. 2. Log the exact fetch lifecycle In your Next.js code, log: - request start time - when headers arrive - response status - response body parse success/failure - actual thrown error Something like:
Copy code
javascript
const start = Date.now();

try {
  console.log("Calling Prefect...");
  const res = await fetch("<http://192.168.29.151:4200/api/health>", {
    headers: {
      Authorization: "Basic " + Buffer.from("astra:xxxxxxxx").toString("base64"),
    },
    cache: "no-store",
  });

  console.log("Status:", res.status, "after", Date.now() - start, "ms");

  const text = await res.text();
  console.log("Body received after", Date.now() - start, "ms", text);
} catch (err) {
  console.error("Fetch failed after", Date.now() - start, "ms", err);
}
3. Check if you are using an AbortController timeout A lot of apps add custom timeouts around
fetch
. If your timeout is too aggressive or not cleaned up correctly, the request can look like a server timeout even when the server responded. 4. Check whether it is actually CORS/auth/body parsing If browser code is calling Prefect directly, possible issues include: - CORS preflight behavior - auth header behavior - parsing non-JSON body as JSON - redirect handling - mixed UI/API requests 5. Compare the exact endpoint Your capture shows some request succeeded, but maybe the failing one is not
/api/health
. The failing endpoint might be: -
/api/...
-
/ui/...
- auth-protected endpoint - websocket upgrade - large JSON endpoint If possible, capture the exact failing path. Best next isolation tests Test 1: direct curl to same endpoint that Next.js calls From the laptop:
Copy code
bash
curl -v -u astra:xxxxxxxx "<http://192.168.29.151:4200/<same-exact-endpoint>>"
If curl succeeds immediately while Next.js times out, the problem is definitely in the app/client layer. Test 2: use Node fetch outside Next.js Create a tiny standalone script on the laptop: ```javascript const start = Date.now(); fetch("http://192.168.29.151:4200/api/health", { headers: { Authorization: "Basic " + Buffer.from("astra:xxxxxxxx").toString("base64"), }, }) .then(async (res) => { console.log("status", res.status, "ms", Date.now() - start); console.log(await res.text()); })
.catch((err) => { console.error("error", Date.now() - start, err); });
Copy code
If this works reliably after idle, but Next.js does not, then it is something in Next.js runtime/code path.

*Test 3: inspect the actual HTTP response*
Run:

```bash
sudo tcpdump -i any -nnvvXSs 0 host 192.168.29.87 and port 4200
That will let you see: - exact request path - response status code - response headers Right now the packet sizes suggest the server probably returned a valid HTTP response, but we haven’t decoded it yet. My conclusion from your latest capture Based on this trace alone: - Prefect accepted the connection - Prefect received the request - Prefect sent the response quickly - the client acknowledged receiving it - the client later closed the connection So this specific request does not support “Prefect timed out before responding”. It suggests the timeout/failure is happening: - in Next.js fetch handling - in browser/client logic - or on a different request than the one captured If you share the exact Next.js fetch code that calls Prefect, I can probably pinpoint the issue faster. The main things I’d look for are: - custom timeout wrappers -
await res.json()
on non-JSON response - SSR/client mismatch - multiple parallel requests - stale auth header / CORS path confusion