all writing security

Security Groups Are Not a Standard. Comparing AWS, Azure, and GCP Firewall Models

If you’ve operated across more than one hyperscaler, you already know the uncomfortable truth: “security group” doesn’t mean one thing. It means three different enforcement models, three different reference primitives, and three different sets of limits that will eventually constrain your architecture whether you’ve planned for it or not.

This matters more than it sounds. Multicloud network and security design — the daily reality for European enterprises running sovereign or hybrid estates — depends on knowing precisely where each platform’s model breaks down, not just how to configure it. Below is a working reference: how each cloud enforces traffic control, how group references actually behave, and the limits that will eventually show up in a design review.


AWS: Security Groups

How they work

AWS security groups are stateful, ENI-level virtual firewalls.

That last point is the architecturally important one. Referencing an SG as a source decouples the rule from IP addressing entirely. The rule means “allow traffic from any ENI carrying this SG,” evaluated against group membership at connection time — not against a baked-in address. Autoscaled or replaced instances stay covered without a single rule edit. A standard three-tier pattern — web SG open on 443, app SG permitting only the web SG on 8080, database SG permitting only the app SG on 5432 — achieves a tiered trust model with zero CIDR blocks anywhere in it.

Cross-account references are also possible (account-id/sg-id), which is the mechanism behind most hub-spoke and shared-services VPC designs.

Multiple SGs on one ENI

An ENI can carry up to 5 SGs by default. Critically, rules across multiple SGs are additive, never subtractive. If one SG allows port 22 and another allows port 443, the ENI permits both — there is no ordering, no “first match wins,” and no way for one SG to override what another has opened. Five loosely governed SGs on an interface is five attack surfaces ORed together, not ANDed. Auditing has to reason about the union, not any individual SG.

Limits

LimitDefaultAdjustable?
Security groups per VPC (per region/account)2,500Yes, soft
Security groups per ENI5Yes, soft — up to 16
Inbound rules per SG60Yes, soft
Outbound rules per SG60Yes, soft
Rules per ENI1,000 — hard ceiling, not adjustable

The real governing constraint isn’t any single quota — it’s the product of SGs-per-ENI and rules-per-SG, which AWS caps at 1,000. Raise rules-per-SG to 250 and your SGs-per-ENI quota correspondingly drops to 4, because 4 × 250 = 1,000. Push past that combination and you’ve hit a wall no support ticket will move.

IPv4 and IPv6 rule counts are tracked as separate quotas (60 inbound IPv4, 60 inbound IPv6, and the same for outbound), so the realistic per-SG ceiling can run higher than 120 in dual-stack environments.

One newer wrinkle worth flagging for shared-VPC and multi-account topologies: when a participant account uses a security group shared via AWS RAM, the effective “SGs per ENI” quota is the lower of the owner’s and the participant’s individual quotas. In a hub-spoke design spanning several accounts, your binding limit is whichever account in the chain is most restrictive — not your own configuration.

Prefix lists are the standard mitigation when you’re CIDR-rule-bound. A single rule referencing a prefix list with up to 1,000 entries counts as one rule against your quota, not N rules.

Cisco mapping: think zone-based firewall policy with implicit reflexive ACLs — stateful, identity-adjacent through SG references, but without the explicit deny or rule-ordering of a real ACL. NACLs (subnet-level, stateless, ordered, support explicit deny) are the closer analog to a numbered Cisco ACL.


Azure: Network Security Groups (NSGs)

How they work

Azure NSGs are also stateful, but diverge from AWS in two structurally important ways.

First, NSGs attach at two points simultaneously — subnet level and NIC level — and you can place the same or different NSGs at both. Inbound traffic must clear the subnet NSG and the NIC NSG in sequence; outbound is evaluated in reverse. This is a materially different model from AWS, where the SG only ever sits at the ENI.

Second, NSGs support explicit deny rules, evaluated in priority order (lower number processed first, first match wins), and ship with six default rules including a DenyAllInbound and DenyAllOutbound that anchor the bottom of every NSG’s rule set. Default rules can’t be deleted, only overridden by a higher-priority custom rule. This is genuinely closer to a classic ordered ACL than AWS’s allow-only model — a higher-priority deny rule can claw back something a lower-priority allow would otherwise have granted, which AWS security groups simply cannot express.

Referencing another group — Application Security Groups

Azure’s version of “reference another group as a source” isn’t NSG-to-NSG. It’s a separate object: the Application Security Group (ASG). You tag NICs with an ASG, then write NSG rules with the ASG as source or destination instead of a CIDR. The outcome is functionally identical to AWS’s SG-reference pattern — membership-based, not address-based — but it’s implemented as a distinct construct layered underneath the NSG rather than the NSG referencing itself.

Multiple NSGs / layered evaluation

Because NSGs can exist at both the subnet and the NIC, opening a single port to a VM behind three layered NSGs (VNet, subnet, NIC) requires an explicit allow at every layer the traffic crosses. This is a chained, ordered model — closer to ASA zone-pairs than to AWS’s flat OR-composition of multiple SGs on one interface. Within a single NSG, rules are strictly ordered with first-match-wins semantics, not unioned.

Limits

LimitDefaultAdjustable?
NSGs per region/subscription5,000Yes, soft
Rules per NSG (inbound + outbound combined)1,000Hard limit, not adjustable
Priority range available100–4096n/a — exists to leave gaps for rule insertion, not to raise the 1,000-rule ceiling
Unique ASGs referenceable within a single NSG~100Per community-confirmed testing; the cap is on unique ASGs, not on the number of rules that reference them

Cisco mapping: NSG behavior is the closest of the three platforms to a true numbered ACL — ordered evaluation, explicit deny, ability to override a broader allow with a narrower deny. The dual subnet-plus-NIC attachment point mirrors applying an ACL at both a VLAN SVI and an individual switchport: defense in depth by design, not by accident.


GCP: VPC Firewall Rules

How they work

GCP departs from both AWS and Azure architecturally. There is no per-ENI or per-subnet attachment object at all — firewall rules are global within the VPC network and project, and every VPC functions as a distributed firewall. Rules are defined once at the network level; enforcement is applied per-instance based on what each rule targets, not on where the rule is attached.

GCP rules support both explicit allow and explicit deny, evaluated by priority (0 is highest, lower wins) — the same ordered-evaluation philosophy as Azure, but applied across the entire VPC rather than at discrete attachment points. Default posture is deny-ingress, allow-egress, matching AWS and Azure.

Referencing another group — tags and service accounts, not group IDs

GCP has no SG-ID or ASG-style object whatsoever. Source and target matching instead uses one of two mechanisms:

Critically, a single firewall rule cannot mix target service accounts and target network tags — each rule picks one mechanism, no hybrid.

This is the architecturally interesting point for anyone thinking in zero-trust terms: service-account targeting is workload-identity-bound, not network-topology-bound. It is the strongest “identity-native” primitive of the three clouds — closer in spirit to policy-engine-driven access than either AWS’s SG-membership model or Azure’s ASG-membership model, both of which remain fundamentally topology references even when group-based.

It is still, however, standing access once granted — static and persistent, with none of the time-bound, ephemeral revocation that an intent-driven access fabric provides on top.

Limits

LimitDefaultAdjustable?
Firewall rules per project (classic VPC firewall)200Yes — to 500 via quota request
Source tags per rule30Fixed maximum
Target tags per rule70Fixed maximum
Source service accounts per rule10Fixed maximum
Target service accounts per rule10Fixed maximum
Hierarchical firewall policy rules (org/folder level)Separate quotaNot counted against the 200/project limit

One operational note worth knowing if you’re scoping a GCP environment right now: Google has been mid-rollout on raising the default project firewall-rule quota from 200 to 300. During a rollout window, the console can display the new ceiling before a given project actually has it provisioned. The reliable check is gcloud compute project-info describe --project PROJECT_ID, not the console quota display.

For environments that genuinely outgrow the per-project model, hierarchical firewall policies (organization- or folder-level, evaluated before VPC-level rules) sit outside the 200/500 ceiling entirely and are the correct lever — not a quota increase request.

Cisco mapping: closest to a global, org-wide ACL applied at every interface simultaneously by policy match rather than physical or logical attachment. There is no “interface ACL” concept at all — the network is policy-driven metadata rather than a topology of attachment points, which tracks with GCP’s broader infrastructure philosophy.


The three models side by side

DimensionAWS Security GroupAzure NSGGCP VPC Firewall
Attachment pointENI onlySubnet + NIC (dual)Whole VPC (global)
Explicit denyNo — allow-onlyYesYes
Evaluation logicUnion / OR, unorderedOrdered, first-match-winsOrdered, first-match-wins
Group reference primitiveSecurity Group IDApplication Security GroupNetwork tag or service account
Closest to workload identityTopology (SG membership)Topology (ASG membership)True identity (service account)
Hard rule ceiling1,000 / ENI1,000 / NSG200–500 / project (soft); unlimited via hierarchical policy

Why this matters beyond trivia

None of these three models gets you to zero trust on its own — and that’s the point worth sitting with. AWS’s SG-reference pattern and Azure’s ASG pattern are both topology-bound: they describe network membership, not workload identity, and certainly not time-bound access. GCP’s service-account targeting gets genuinely closer to identity-native enforcement, but it’s still standing access, granted once and held indefinitely until someone remembers to revoke it.

That gap — between “permitted because you’re in the right group” and “permitted because you proved who you are, for exactly as long as you need to be permitted, with the access automatically expiring” — is the entire reason intent-driven, ephemeral access fabrics exist as a category. Security groups, NSGs, and VPC firewall rules are necessary infrastructure. They are not, on their own, a sovereignty or zero-trust strategy. Knowing precisely where each platform’s native model stops is the first step in deciding what has to sit above it.


Sources: AWS VPC quotas documentation, AWS re:Post security group rule guidance, Microsoft Learn NSG documentation and community Q&A, Google Cloud VPC and Cloud NGFW quotas documentation. Limits current as of this writing — always verify against the live Service Quotas / Azure Limits / Google Cloud Quotas console for your account, as hyperscalers adjust these figures over time without much fanfare.

Written by Paul Carvill

Enterprise → cloud → AI networking. I write the breakdowns I wish I’d had. New field notes roughly twice a month.

keep reading

More writing