Connect a Heroku App to Azure SQL Database With a Static IP Using QGTunnel

QuotaGuard Engineering
June 25, 2026
5 min read
Pattern

Azure SQL's firewall allows connections by client IP, and Heroku dynos rotate that IP on every deploy. Route the 1433 connection through QGTunnel so Azure SQL always sees your two static IPs.

Azure SQL Database blocks every connection until you add the client's IP to its firewall. Heroku dynos use rotating outbound IPs that change on deploy and restart, so a firewall rule you set today stops matching tomorrow and the connection drops. Because Azure SQL speaks TDS over TCP port 1433, not HTTP, an HTTP proxy won't carry it. QGTunnel does. This post shows the setup.

This is for developers running a Heroku app that connects to an Azure SQL Database and keep having to update the Azure firewall rule by hand every time Heroku reassigns their dyno's IP.

Azure SQL Grants Access by Client IP, and Heroku's IP Keeps Changing

Azure SQL Database's firewall prevents all access until you explicitly add the IP addresses of the clients allowed to connect. Microsoft's own guidance for clients on dynamic IPs is direct: get static IP addressing for your client, then add those IPs as firewall rules. That's exactly the situation a Heroku app is in. Heroku doesn't give a dyno a fixed outbound IP, so there's nothing stable to put in the Azure firewall rule.

The result is a maintenance loop: the connection works right after you add the current dyno IP, then a deploy moves the app to a new dyno with a new IP, the firewall rule no longer matches, and Azure SQL refuses the connection until you update the rule again.

SQL Server Connections Need QGTunnel, Not an HTTP Proxy

The standard QuotaGuard HTTP proxy handles HTTP and HTTPS traffic. Azure SQL on port 1433 is raw TCP using the TDS protocol, so an HTTP proxy can't intercept it. QGTunnel is the tool for this.

QGTunnel is a lightweight binary that wraps your app's process and routes outbound TCP connections through QuotaGuard's infrastructure. Your connection string doesn't change. Your app's SQL driver sees a normal connection. Azure SQL sees traffic arriving from your two static IPs.

For a database connection carrying business data, use QuotaGuard Shield rather than Static. Shield uses SSL passthrough, so the encrypted connection runs end-to-end between your app and Azure SQL and QuotaGuard never decrypts it. For data going into a SQL database, that's the right architecture.

Step 1: Get Your Shield URL and Static IPs

Log into your QuotaGuard dashboard and copy your Shield connection URL. Note your two static egress IP addresses on the same page. You'll add both to the Azure SQL firewall in the next step.

Step 2: Add Both Static IPs to the Azure SQL Firewall

In the Azure portal, open your logical SQL server, go to Networking or the firewall settings, and add a server-level firewall rule for each of your two QuotaGuard static IPs.

  1. Open your Azure SQL server in the portal.
  2. Go to the Networking settings and find Firewall rules.
  3. Add a rule for your first QuotaGuard IP, setting the start and end IP to the same address. Repeat for the second IP.
  4. Save. Azure notes that rule changes can take a few minutes to take effect.

QuotaGuard tip: add both static IPs now, even if traffic appears to come from only one at first. QuotaGuard load-balances across the pair, and a firewall rule that includes only one IP causes intermittent connection failures that are painful to debug.

Step 3: Add QGTunnel to Your Heroku App

QGTunnel is a binary you add to your project, configure to point at your Azure SQL server, and wrap your start command with. When QuotaGuard Shield is provisioned, the add-on sets the QUOTAGUARDSHIELD_URL config var automatically and QGTunnel reads it directly, so there's no separate credential step.

Download the QGTunnel binary into your project root:

curl https://s3.amazonaws.com/quotaguard/qgtunnel-latest.tar.gz | tar xz

Create a .qgtunnel config file that maps a local port to your Azure SQL server. In transparent mode, your app connects to the server normally and QGTunnel intercepts the connection:

[qgtunnel.azuresql]
accept = "127.0.0.1:1433"
connect = "your-server.database.windows.net:1433"
transparent = true
encrypted = false

You can generate this config from your QuotaGuard dashboard (open the add-on, then Setup, then QGTunnel Configuration) and download it to persist it with your app, which avoids a runtime dependency on the QGTunnel API during Heroku restarts.

Wrap your process start command with qgtunnel in your Procfile, replacing the example with your app's actual start command:

web: bin/qgtunnel node server.js

Commit the qgtunnel binary, the .qgtunnel config file, and (for transparent mode) the vendored nss_wrapper library to your repo so they deploy with the app. Your app's connection string still points at your Azure SQL server hostname. The tunneling is transparent to the SQL driver, which sees a normal connection while the traffic exits from your two QuotaGuard static IPs.

Step 4: Verify the Connection

Deploy and confirm the app connects to Azure SQL through the tunnel. If it connects, redeploy as many times as you want, the IPs Azure SQL sees are your two static QuotaGuard IPs and they don't change.

If the connection fails, two causes cover most cases. First, the Azure firewall rule doesn't have both exact QuotaGuard IPs, check both are present. Second, the SQL login or connection string is wrong in a way unrelated to the IP, confirm the credentials and that the server allows SQL authentication for remote connections.

Why This Works When a Standard Proxy Doesn't

The HTTP proxy approach works for anything speaking HTTP or HTTPS. Azure SQL over port 1433 is a different protocol that opens a raw TCP connection and speaks TDS. Standard HTTP proxies don't handle it. QGTunnel operates below the application layer, intercepts the outbound TCP connection to your configured destination, and tunnels it through QuotaGuard. The SQL driver just sees a normal connection.

Get a Static IP for Your Heroku to Azure SQL Connection

Azure SQL's firewall needs a stable client IP, and Heroku's rotating dyno IPs can't provide one. QGTunnel plus QuotaGuard gives Azure SQL two static IPs that stay valid across every deploy, so you set the firewall rule once and stop hand-editing it.

QuotaGuard Shield plans start at $29 per month on a direct plan. For a database connection carrying business data, SSL passthrough is the right architecture. See QuotaGuard Shield for details, or see plans at quotaguard.com/products/pricing. To talk through a specific Heroku to Azure SQL setup, contact us and an engineer will respond directly.

QuotaGuard Static IP Blog

Practical notes on routing cloud and AI traffic through Static IPs.

Reliability Engineered for the Modern Cloud

For over a decade, QuotaGuard has provided reliable, high-performance static IP and proxy solutions for cloud environments like Heroku, Kubernetes, and AWS.

Get the fixed identity and security your application needs today.