Firstly, Nat 0 and static can be used to achieve the same result of bypassing NAT, at least logically 🙂
However both are fundamentally different.
Take a look at the following example:
nat (inside) 0 192.168.1.1 255.255.255.255
static (inside,dmz) 192.168.1.1 192.168.1.1 netmask 255.255.255.255
Both statements preserves the IP address 192.168.1.1 for traffic going from inside to dmz.
Statement 1 (nat 0) however is outbound only. Only traffic initiated from the inside gets natted (or bypasses natting). A ping from the DMZ network will not be able to reach the inside host 192.168.1.1 even with ACLs.
Statement 2 (static) however creates a static (permanent) NAT entry in the firewalls table which all. This allows networks in the DMZ zone to access the IP in the inside zone ie. inbound. Providing that you have the correct ACL, a ping initiated from the DMZ to 192.168.1.1 will work.
Hence static is commonly used when traffic needs to flow from a lower security zone to higher security zone. I.e Outside -> DMZ -> Inside.
Where as NAT 0 is used from Higher to lower if you do not want the lower zone traffic to reach back. I.e Inside -> DMZ -> Outside
Note: Don’t confuse this with stateful firewall inspection. As the firewall allows return packets from the destination when initiated by the source.