An Azure service that provides an event-driven serverless compute platform.
Hi @alexbf ,
One thing you may want to try is simplifying the SQL connection string and explicitly using the TCP format, as this has resolved similar intermittent connectivity issues in some environments.
You could test changing from:
Server=<myserver>,1433;Initial Catalog=<myDatabase>;Persist Security Info=False;User ID=<MyId>;Password=<Password>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Packet Size=32767
to:
Server=tcp:<myserver>;Initial Catalog=<myDatabase>;User ID=<MyId>;Password=<Password>;Packet Size=32767;TrustServerCertificate=True;
In some cases, this change can influence how the client establishes and negotiates the connection (especially over VNET/private routing paths), which may help avoid intermittent transport-level resets.
- Does
Microsoft.Data.SqlClientopen TCP beforeOpenAsync()returns, and can RST explain SQL Server seeing a session?
OpenAsync() does not return until the full connection is established, which includes TCP handshake, TLS handshake (since Encrypt=True), SQL Server login (TDS pre-login + login phase)
So, if SQL Server shows a session in sys.dm_exec_sessions, it means the connection successfully completed login.
A physical TCP RST can still occur immediately after this point (or during early post-login), which would result in:
SQL Server seeing a session briefly created
No subsequent command arriving
Client reporting “connection reset by peer”
So yes, this pattern is consistent with a post-login abort/reset rather than a failed OpenAsync().
- Does
ConnectRetryCount=3create new TCP connections per retry and multiple sessions in SQL Server?
Yes, but only during the connection establishment phase inside OpenAsync().
If a transient failure occurs during login:
SqlClient will retry by creating a new physical TCP connection each attempt
SQL Server will see multiple short-lived login sessions for failed attempts
Only the final successful attempt results in a stable session
However, in your scenario (where a session exists but no command arrives), this does not align with ConnectRetry behavior, because retries happen before the connection is handed to application code.
- Could anything else explain this (thread pool starvation, Azure Functions host behavior, etc.)?
Yes, and these are actually more likely than SQL Client internals:
Azure Functions / Host-level factors:
Worker process restart or recycle (common in isolated .NET worker)
Timer trigger execution being interrupted
Scale-in/scale-out events
Memory pressure leading to host shutdown
App domain / worker restart mid-execution
These can result in SQL connection being established successfully and then abruptly aborted before first command execution
Thread pool starvation (secondary possibility):
- If the .NET thread pool is saturated, continuation after
OpenAsync()or beforeExecuteNonQueryAsync()can be delayed - This delay can indirectly cause network intermediaries to reset the connection due to inactivity or perceived stall
- Any known experience with TCP error 35 in Azure Functions + VNET SQL Server?
This error pattern is commonly observed in Azure Functions (especially timer-triggered or burst workloads), Private VNET / peered VNET SQL Server connectivity, Long-lived connections with sequential command execution
Typical root causes reported include:
Function host recycling or cold start interruptions
Network device / firewall / NAT idle or inspection timeouts
Intermittent TCP resets in VNET routing paths
Thread pool pressure under burst execution leading to delayed SQL packet send
Importantly, this is usually not a SQL Server issue, since the server-side session exists and is ready but never receives the first request payload.