AWS Security Group vs NACL — When Should You Use Which?
A practical comparison of AWS Security Groups and Network ACLs. Covers stateful vs stateless behavior, instance-level vs subnet-level protection, typical production patterns, and common misunderstandings.
Why People Confuse Them
When designing AWS networks, teams often ask:
- Is a Security Group enough?
- Do we also need NACLs?
- What is the real difference if both have inbound and outbound rules?
In practice, Security Groups are the default control, while NACLs are usually a secondary control for more specific subnet-level policies.
The Simplest Way to Remember the Difference
- Security Group: instance or ENI level, stateful
- NACL: subnet level, stateless
That one distinction explains most of the operational difference.
Security Group Characteristics
- attached to ENIs
- allow rules only
- stateful
- can reference other Security Groups
Example:
App SG
- Inbound: 8080 from ALB SG
- Outbound: 5432 to DB SG
This is usually the easiest pattern to maintain.
NACL Characteristics
- attached to subnets
- supports both allow and deny
- stateless
- evaluated in rule order
Because NACLs are stateless, return traffic ports must also be allowed explicitly.
Why Stateful vs Stateless Matters
With Security Groups, if a request is allowed in, return traffic is automatically allowed out.
With NACLs, that is not true.
That makes NACLs easier to misconfigure, especially around ephemeral ports.
Common Real-World Usage Pattern
Typical recommendation:
- use Security Groups as the main access control
- use NACLs only when you need subnet-level deny behavior or strong network boundary policies
That keeps operations simpler and debugging faster.
Common Misunderstandings
”NACLs are stronger, so we should always use both heavily”
Not necessarily. More controls can also mean more operational mistakes.
”Security Groups only protect EC2”
They protect ENIs, so they matter for many AWS resources including ALB and RDS.
”Tighter NACLs are always safer”
Only if they are correct. Broken NACLs often block normal traffic and complicate incident response.
Recommended Pattern
For most service-to-service communication:
- ALB SG
- App SG
- DB SG
That is usually enough.
Use NACLs only when there is a clear need such as broad IP-range denial at the subnet boundary.
Troubleshooting Order
When traffic fails, check:
- Security Groups
- Route tables
- NACLs
In many environments, the issue is more often SG or routing than NACL.
Closing Thoughts
In AWS network security, the goal is not to use every possible control. It is to keep boundaries simple and explainable.
Security Groups usually provide the primary protection. NACLs are best used carefully and intentionally.