TL;DR
If you run many AWS Glue jobs concurrently inside a VPC, your concurrency
ceiling is the number of free IPs in a single subnet, not the sum of
free IPs across your VPC. Attaching multiple Glue connections does not
pool IPs across subnets; it only provides failover. I proved this with a
series of controlled tests, and the fix is boring but effective: size a
dedicated subnet per workload to workers_per_job x max_concurrency.
The setup
I work on a regulated data platform where several products share one
VPC. Each product runs a set of Glue ETL jobs. I started hitting failures
under concurrency with errors like:
The specified subnet does not have enough free addresses to satisfy the
request. Please provide a connection with a subnet with ips available.
On paper I had plenty of headroom, ~96 free IPs across six subnets. So
why were jobs failing at 8-10 concurrent runs? The answer is in how Glue
consumes IPs.
The mental model: ENIs = workers = IPs
When a Glue job connects to VPC resources, Glue creates Elastic Network
Interfaces (ENIs) in your subnet. The number of ENIs tracks the number of
workers (DPUs) for the job, and each ENI consumes one private IP in the
subnet.
So a single job with 4 workers ~= 4 IPs. Ten such jobs running at once ~= 40
IPs, all drawn from one subnet. That's the part that surprises people.
The myth: "multiple connections give me more IPs"
A Glue job can have multiple connections attached, and each connection can
point to a different subnet. It's tempting to assume Glue will spread ENIs
across those subnets to pool IP capacity. It won't.
Here's what actually happens:
- Glue evaluates connections in the order they're listed and picks the first suitable one. All ENIs for that run are created in that one subnet, in a single AZ.
- Additional connections are failover only: Glue rolls over to the next connection if the first has a networking/AZ problem. It is not load-balancing and not high availability.
- Multiple connections to the same subnet with different DB URLs just means "reach different databases," not "get more IPs."
- Glue does not switch connections dynamically mid-run to chase free IPs.
Net effect: your effective IP budget is the free-IP count of whichever single
subnet Glue lands on, usually your largest one.
The experiments
I ran a controlled matrix to pin down the behavior. Subnet labels are
generic; the numbers are representative.
| # | Jobs submitted | Subnet(s) | Available IPs | Workers/job | Glue ver | IPs used | Result |
|---|---|---|---|---|---|---|---|
| 1 | 3 | Subnet-A | 26 | 4 | 3.0 | 12 | Passed |
| 2 | 3 | Subnet-A | 26 | 4, 3, 2 | 3.0 | 9 | Passed |
| 3 | 3 | Subnet-A | 26 | max 4 (autoscale) | 3.0 | 12 | Passed |
| 4 | 1 | Subnet-A | 26 | 4 | 4.0 | 4 | Passed |
| 5 | 8 | Subnet-A + B | 52 (26+26) | 4 | 3.0 | 26 | 6 succeeded, 2 failed |
| 6 | 10 | Subnet-A + B | 36 | max 4 (autoscale) | 3.0 | 27 | All succeeded |
The two multi-subnet tests are the interesting ones:
- Test 5: Two subnets attached (26 free IPs each). Eight jobs at 4 workers need 32 IPs. Only the first subnet was used: it holds 26 IPs, so 6 jobs got their 24 IPs and the remaining 2 failed for lack of addresses. Zero IPs were drawn from the second subnet.
- Test 6: Ten jobs with auto-scaling enabled. All succeeded, but every ENI still came from a single subnet. Auto-scaling let the jobs fit into fewer IPs; it did not spread them across subnets.
What I observed
- A Glue job can attach multiple connections; each points to a subnet.
- Glue uses exactly one connection/subnet per job run.
- Connection selection is order-based, with rollover only on failure: it's failover, not balancing.
- Multiple connections to the same subnet = access to different databases, not more IPs.
- Multiple connections exist for fault tolerance/failover, never for HA or IP pooling.
- With auto-scaling on, N concurrent jobs all land in the single subnet of the first working connection.
- With auto-scaling off, jobs beyond the subnet's IP budget fail outright.
- Partial free IPs are not shared across subnets.
- Therefore, spreading IPs thinly across many subnets buys you nothing: Glue won't switch subnets to use them.
The capacity math
Plan per single subnet, not per VPC:
IPs needed ~= workers_per_job x max_concurrent_jobs
Then remember AWS reserves 5 IPs in every subnet, and leave a little ENI
headroom. Worked examples:
-
10 concurrent x 4 workers = 40 IPs in one subnet.
A
/27(32 total, ~27 usable) can't do it. You need at least a/26(64 total, ~59 usable). -
5 concurrent x 4 workers = 20 IPs.
A
/27(~27 usable) is comfortable.
My original layout, six small subnets (/27s and /28s) totaling ~96 free
IPs, looked generous but capped me at ~26 concurrent-worker-IPs because Glue
only ever touched one /27.
What I changed
-
One dedicated subnet per workload, sized to that workload's peak
workers x concurrency. Workload A gets its own/27; the heavier Workload B gets a larger block. - Stopped treating multiple connections as capacity. They're failover. If I genuinely need cross-VPC reachability, that's VPC peering, which is about reachability, still not IP pooling.
- Used auto-scaling deliberately. It reduces IP pressure but adds latency for large table ingests, so it's a conscious trade-off, not a free win.
- Evaluated Glue job queuing. AWS's built-in job queuing automatically handles concurrency limits and retries jobs instead of failing them immediately, worth enabling if bursty submission is your pattern.
Key takeaways
- Glue concurrency is bounded by one subnet's free IPs, full stop.
- ENIs = workers = IPs. Budget accordingly.
- Multiple connections = failover, not more capacity.
- Right-size a dedicated subnet per workload; don't scatter IPs across many small subnets and expect Glue to pool them.
Top comments (0)