Azure SQL serverless: the first connection fails with error 40613, and the auto-pause settings behind it
A paused serverless database answers its first connection with error 40613 and resumes in the background, usually within a minute; everything after that is about retries and the auto-pause delay. The retry settings per driver that ride out the resume, what stops a database pausing at all, how to see the sessions holding it open, and when serverless costs more than provisioned.
Data & storageFix a problem7 min read
The Azure SQL serverless tier pauses a database that has had no sessions and no CPU for as long as its auto-pause delay, and the next login wakes it. That login is the one that fails: the server returns error 40613, "Database on server is not currently available", starts the resume, and the database is generally back within a minute. Nothing is broken. What's missing is a client that tries again, and that's a setting, not a code change, in every driver Microsoft ships. This guide gives the setting for each, then the other half of the story: why a database you expected to pause never does, and when serverless is the wrong tier for the bill.
Why the first connection fails
Auto-pause starts when, for the whole of the auto-pause delay, the database has had zero sessions and zero CPU in the user resource pool. The delay defaults to 60 minutes; the minimum is 15 minutes in the General Purpose tier (60 in the Hyperscale preview), the maximum is seven days, and -1 disables pausing. Pausing itself takes one to ten minutes once the conditions are met, and resuming about a minute, though either can be as quick as a second.
While paused, the database still exists: the first login or other activity resumes it, and because the resume takes time, that first attempt is refused with 40613. Microsoft's position is that every cloud-connected application needs retry logic for transient errors anyway, and that a serverless database merely makes one of those errors predictable. 40613 is in the transient-error lists the drivers already carry, so a correctly configured driver retries it without any code of yours.
Three ways people meet it:
- An overnight job's first query fails and the job aborts, because the job runs its own connection with the default timeout.
- A canvas app over the SQL Server connector shows a data error on the first screen of the morning, then works on the second try. Whether the connector retries isn't documented, so treat the first call after idle as something to design for: a longer delay, no pause during working hours, or a flow that touches the database before people arrive.
- A health check marks the database down once an hour, because it's the only thing connecting and it's also what wakes it.
Retry settings that cover the resume
The pattern is the same everywhere: the first attempt fails fast, so a longer timeout on its own does nothing; a retry count on its own is cut short by the timeout. Set the count, the interval between retries and the login timeout as a group, so the sequence lasts about a minute.
| Driver | What the default does | Set instead |
|---|---|---|
| SqlClient (.NET) | ConnectRetryCount 1, ConnectRetryInterval 10 seconds, Connection Timeout 15 seconds. The first attempt counts as try zero; the one retry happens after 10 seconds, inside a 15-second budget | ConnectRetryCount=5;ConnectRetryInterval=10;Connect Timeout=90 in the connection string. Microsoft.Data.SqlClient also has configurable retry logic for commands, not just connections |
| Entity Framework Core | No retries unless you ask | options.UseSqlServer(cs, o => o.EnableRetryOnFailure()): 6 retries and a 30-second maximum delay by default, with Azure SQL's transient error numbers pre-loaded. Code that opens its own transaction has to run inside CreateExecutionStrategy().ExecuteAsync(...), or EF throws that the retrying strategy doesn't support user-initiated transactions |
| JDBC | connectRetryCount 1, retried at once, so both attempts land during the resume | loginTimeout=120;connectRetryCount=5;connectRetryInterval=15 |
| ODBC, OLE DB, PHP | 15-second login timeout and no retry | A login timeout of at least 60 seconds, and a retry loop in the application |
| Python (mssql-python, mssql-django) | Short timeouts | A connect timeout of at least 60 seconds and a retry on the first connection; Django's driver exposes connection_retries and connection_retry_backoff_time |
| Go (go-mssqldb) | No login timeout | Retry logic rather than a longer timeout; Learn says so in as many words |
For a job runner or a Function, wrap the first connection in a retry with backoff up to about 90 seconds, log the attempts, and let the job carry on. The resume happens once; after that the database behaves like any other until it pauses again.
The database never pauses
The opposite complaint is a serverless database billed for compute all month because it never met the pause conditions. Some features keep a database online by design, and you should disable auto-pause rather than wonder:
- active geo-replication and failover groups;
- long-term backup retention;
- a DNS alias on the logical server;
- the sync database in SQL Data Sync (hub and member databases can still pause);
- a serverless database used as the job database for elastic jobs (databases that jobs target can pause; a job connection resumes them);
- some service updates, temporarily, until the update completes.
With none of those in play, Learn is blunt about the most common cause: open sessions, with or without any CPU. Something is connected. Find it:
SELECT session_id, login_name, host_name, program_name, status, last_request_end_time
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;
Then disconnect, because the session you just used to run that query is itself a reason not to pause. If the list is empty now but the database still didn't pause overnight, something connected during the delay period; Auditing shows who, and when.
The usual names in program_name: a monitoring agent polling every few minutes, an application's connection pool with a keep-alive, a scheduled Power BI refresh or a flow on a timer, a management studio someone left open, and your own health check. Each of them resets the clock. Either move them out of the quiet hours, or accept that this database isn't idle and shouldn't be serverless.
Is serverless saving money?
Serverless bills compute per second between the minimum and maximum vCores you set, charges the minimum when usage is below it, and charges nothing for compute while paused (storage is billed as usual). Two consequences people miss:
- the minimum compute bill scales with the maximum you configure, so a wide range isn't free at the bottom;
- Azure Hybrid Benefit and reservations don't apply to serverless.
So a database that's busy most of the day, or that never pauses because of the section above, usually costs less as provisioned compute with a reservation. Serverless earns its keep for databases that are genuinely idle for long stretches: development and test, internal tools used in office hours, seasonal workloads. Set the delay to match (a few hours for a dev database, -1 for anything a customer waits on), and put the retry settings in before the first Monday morning.
Sources
- Auto-pause and auto-resume in the serverless compute tier for Azure SQL Database, Microsoft Learn (the conditions, 40613, the features that prevent pausing, the sessions query, latency)
- Serverless compute tier for Azure SQL Database, Microsoft Learn (the delay's defaults and limits, cost)
- Azure SQL Database serverless compute tier FAQ, Microsoft Learn (billing, Hybrid Benefit and reservations)
- Troubleshoot transient connection errors, Microsoft Learn (the SqlClient retry parameters and their defaults)
- EnableRetryOnFailure, Microsoft Learn (the EF Core defaults)
- Working with data in ASP.NET Core apps, Microsoft Learn (execution strategies and user transactions)
- Connection resiliency (JDBC), Microsoft Learn (the auto-paused database settings)
- Manage connections with mssql-python, Troubleshoot mssql-django and go-mssqldb connection strings, Microsoft Learn
Did this fix it?
Comments
No comments yet. Share what worked for you.
Sign in to comment. Comments show under a display name you choose, never your email.