Updated: October 2026
A rule says "allow outbound 443," the reply never arrives, and nobody can see why. Or a firewall rule gets deleted and the SSH session it allowed keeps running anyway. Both come down to stateful vs stateless: whether the device in the path remembers the conversation or judges every packet on its own.
What Stateful vs Stateless Means
A stateful system remembers what came before. A stateless system doesn't. Every request or packet arrives with no memory of the last one, so it has to carry everything needed to judge it.
Think of two receptionists. The first keeps a visitor log, so when someone walks back in from the car park she waves them through. The second has no log. Every person at the desk gets checked against the list from scratch, including the one who left five minutes ago.
The same split shows up in three places an IT team touches every week: firewalls and cloud network rules, application servers, and the protocols between them. The logic is identical in all three. The consequences aren't.
How a Stateful Firewall Works
A stateful firewall keeps a connection table, also called a state table or session table. When a packet starts a new connection, the firewall checks it against the rules. If it's allowed, the firewall writes an entry: source and destination address, source and destination port, and protocol. That's the five-tuple.
Every packet after that gets matched against the table first. Replies to a connection your side started are let back in automatically, because the firewall knows they belong to something it already approved. You write one rule for the direction the conversation starts in, and the return path takes care of itself.
For TCP the firewall also follows the handshake and the flags. A SYN opens an entry, FIN and RST wind it down, and a stray packet claiming to belong to a connection that never existed gets dropped. UDP has no handshake, so the firewall guesses. It opens an entry on the first packet and closes it when a timer runs out.
Microsoft's docs for Azure network security groups spell out the behaviour that surprises people most. The flow record is what makes the NSG stateful, so an outbound rule on port 80 needs no matching inbound rule for the response. Remove a rule, and existing connections carry on. Only new connections see the change.
The replies in that r/networking thread make a useful point: UDP sessions live on timers alone, which is why firewalls keep them short.
How a Stateless Firewall Works
A stateless firewall, often called a packet filter or an access control list (ACL), checks each packet against its rules and forgets it. It reads the header, compares addresses, ports and protocol, and allows or drops. No table, no memory.
That means the return path needs its own rule. A web server behind a stateless filter needs inbound 443 for requests and an outbound rule for the replies. The replies go to the client's ephemeral port, a temporary high-numbered port the client picked for this one conversation. You can't know which one in advance, so the rule has to open the whole range.
AWS runs both models side by side, which makes it the clearest example. Its VPC documentation puts it in one table row: in a security group, return traffic is "automatically allowed (stateful)"; in a network ACL it "must be explicitly allowed (stateless)." Security groups sit on the instance. Network ACLs sit on the subnet and evaluate rules in number order until one matches.
Stateless filters are still everywhere, just rarely in the job title "firewall." Switch and router ACLs are usually stateless, because hardware can check them at line rate without memory to manage.
One reply comes from an ISP engineer who blocks outbound port 25 on a customer's port when it's sending spam. There's no need for a state table for a rule that blunt, and the router carries it at no extra load.
Stateful vs Stateless Firewall: Side by Side
| Stateful firewall | Stateless filter | |
|---|---|---|
| Remembers connections | Yes, in a connection table | No |
| Return traffic | Allowed automatically | Needs its own rule |
| Rules to write | One per conversation direction | Both directions, including ephemeral port ranges |
| Catches spoofed or out-of-order packets | Yes, it knows which connections exist | No, a packet that matches a rule passes |
| Cost | Memory and CPU per connection | Almost none, often done in hardware |
| Typical home | Perimeter firewalls, Azure NSGs, AWS security groups, Windows Defender Firewall | Router and switch ACLs, AWS network ACLs, simple iptables rules |
| Fails when | The table fills up or an entry times out | A return rule is missing |
The short answer: use stateful filtering where users and servers live, and stateless ACLs as a coarse outer fence. AWS describes network ACLs in exactly those terms, as a secondary control and subnet guard rail behind security groups.
When the State Table Is the Problem
Stateful filtering removes a whole class of rule-writing mistakes. It adds a new class of tickets in exchange, and they all look like "the connection just dies."
Idle timeouts. Every entry in the table has a timer. If a connection goes quiet for longer than the timer, the entry disappears, and the next packet looks like a stranger. Azure Standard Load Balancer defaults to a 4-minute idle timeout, configurable up to 100 minutes, per Microsoft Learn (updated August 2026). A database client that sits idle over lunch then throws a reset is usually this. Fix it with TCP keepalives shorter than the timeout, or raise the timeout on the device in the middle.
Asymmetric routing. A stateful firewall only knows connections it saw start. If the request leaves through firewall A and the reply comes back through firewall B, B has no entry and drops the reply. Two internet links, two firewalls and dynamic routing are the usual recipe. Our guide to network topology covers how those paths get built.
A full table. Tables have a size limit. On Linux, connection tracking logs nf_conntrack: table full, dropping packet when it runs out. The kernel docs set the default timeout for an established TCP entry at 432,000 seconds, five days, so a busy NAT box can fill up with connections that died long ago. Lower the established timeout or raise nf_conntrack_max.
Rules that don't bite. As the Azure docs note, removing a rule doesn't kill connections it already allowed. If you're cutting off access during an incident, clear the sessions too, or the attacker's open session outlives your change.
Stateful vs Stateless Applications
The same idea runs one layer up. A stateless application keeps nothing about the user between requests. Every request carries what the server needs, such as a token, and any server in the pool can answer it. A stateful application keeps session data on the server that handled the last request.
HTTP itself is stateless. Each request stands alone. Logins and shopping carts feel continuous because the app adds state on top, usually with a cookie that points to a session stored somewhere.
Where that session lives decides how the app scales and what breaks during maintenance. If it sits in one web server's memory, the load balancer has to send the user back to that same server every time. That's a sticky session. Reboot the server for patching and everyone pinned to it gets logged out. Move the session into a shared store such as Redis or a database, and the web tier becomes stateless. Any server can go down for patching and nobody notices.
Kubernetes draws the same line in its API. Deployments run stateless pods that can be replaced freely. StatefulSets exist for workloads that need a stable identity and their own storage, such as databases. REST APIs are designed to be stateless by definition.
Nothing is fully stateless. The state moves to a place built to hold it: the database, the session store, the token. For an IT team, the practical question is where that place is, and whether it's backed up.
Which One You Need
For firewalls, the default is stateful at the edge and on every host, with stateless ACLs where you want a cheap, blunt filter in front. For applications, keep the web and app tier stateless and put state in something designed to hold it. In both cases, write down where the state lives, because that's where the next outage ticket will point.
When a connection dies and the rules look right, check the state table before the rule list. Idle timeouts, asymmetric paths and full tables sit behind plenty of "the firewall is blocking it" tickets. For the rest, our walkthrough of DNS server not responding covers the other usual suspect.
Dmytro Koval
Head of Product Engineering
Hi! My name is Dmytro, but everyone calls me Dima. I’m a Software Developer and together with the development team, I help bring Flamingo to life — putting it on its feet from a technical perspective. Originally from Lviv, Ukraine 🇺🇦, but currently based in Spain, where I’ve been enjoying the blend of great weather, culture, and nature. I’m passionate about the mountains and love traveling — exploring new places and cultures really inspires me. These experiences constantly recharge me and give me a fresh perspective, both personally and professionally.
