How Regular Expressions Work Under the Hood

TL;DR: Here's how regular expressions work in one sentence: a regex is a tiny pattern-matching program, and a regex engine runs it against your text. Most engines try every possible match and back off when they fail β flexible, but easy to make slow. Anchoring the pattern and avoiding nested repeats keeps it quick.
You need every failed login in a 200MB log file. You type a pattern into your editor, hit find, and the matches appear in half a second. Run that same pattern on a web server and it can hang for 30 seconds on a single request. Same text, same pattern, very different result.
How regular expressions work, step by step
Take \d{3}-\d{4} β the shape of a phone number like 555-1234. Your code hands that to the engine, which first compiles it into a small map of states, like subway stations joined by tracks.
Then it reads your text one character at a time and walks the map. \d means "any digit", {3} means "exactly three of them", and the hyphen is just a hyphen. Reach the final station and you have a match.
Symbols like * (zero or more) and + (one or more) are loop arrows on that map. ^ and $ pin a match to the start and end of a line. No magic involved β it's a state machine.
Why some regex engines are fast and others are not
There are two families of engine, and the difference decides whether your pattern finishes in a millisecond or never.
- Deterministic engines walk the text once and never go back. Time grows in a straight line with text length. You'll find them in RE2 (Google's engine), Rust's regex crate, Go, and most
grepbuilds. - Backtracking engines try a path, fail, rewind, and try another. That's how they support extras like backreferences (
\1) and lookarounds ((?=...)). JavaScript, Python'sre, Java, PHP, .NET and PCRE all work this way.
Backtracking is where trouble starts. Give one the pattern (a+)+$ and 30 a's followed by a !, and it can try roughly a billion paths before giving up. One short string, one frozen server. That's catastrophic backtracking, and it's the engine behind ReDoS (regex denial of service) attacks.
The checklist for regex that stays fast
A regex cheat sheet covers the syntax. This list covers the traps.
- Anchor it. Start with
^unless you want matches mid-text. It stops pointless scanning. - Say what you mean.
[a-z]beats.because the engine has fewer options to try. - Never nest repeats.
(a+)+,(.*)*and(\w+\s?)+are the classic freeze patterns. Flatten them into one repeat. - Use lazy quantifiers when you want the shortest match.
.*?stops at the first chance;.*runs to the end. - Test ugly input. Empty strings, 10,000-character lines, emoji, and your own data with a typo in it.
- Set a time limit. Python's
regexmodule, .NET and Java all let you cap how long a match may run.
What this means for you
A quick find-and-replace in your editor? Use any pattern you like. Code that runs on a server? Treat every pattern as a possible outage.
Three habits save you. Never run a raw regex a user typed in. Use a library for email and URL checks instead of a 200-character monster. And pick a linear-time engine when you can. Validating an email address? Check for one @ and a dot in the domain, then send a confirmation link. That beats any regex.
Key Takeaways
- A regex gets compiled into a state machine, then run character by character over your text.
- Fast engines match in one pass; backtracking engines rewind and retry, which adds features but can explode.
- Nested repeats like
(a+)+cause most freezes and ReDoS attacks. - Anchor your patterns, avoid
.when you can be specific, and never run user-supplied regex without a timeout.
Frequently Asked Questions
What is regex in plain English?
A regex is a text pattern that describes a set of strings. You describe what you're looking for once, and the engine finds every match in a file or form field.
Why does my regex work in one language and fail in another?
Each language ships a different engine. Lookarounds and backreferences exist in JavaScript and Python but not in Go or RE2, and \d can match non-English digits in some engines. Check the engine, not just the syntax.
How do I stop a regex from hanging?
Anchor it, remove nested repeats, and set a match timeout. If a user supplies the pattern, run it in a separate process you can kill.
How did this story feel?
Be the first to react
Recommended gear
Popular tech picks
Samsung Galaxy S25 Ultra
6.9" AMOLED Β· 200MP Β· 5000mAh
Editor's pickView on Amazon βApple MacBook Air 13-inch (M4)
M4 Β· 16GB Β· 13.6" Liquid Retina
Editor's pickView on Amazon βSony WH-1000XM5
Over-ear ANC Β· 30h battery
Best headphonesView on Amazon βAffiliate links: we may earn a commission at no extra cost to you.
Written by
TechPulse Team
The TechPulse editorial team publishes clear, practical technology guides. Every article is original and written to be understood β not just skimmed.
Comments (0)
No comments yet β start the conversation!
Keep reading

How to Pick Your First Programming Language
Stop comparing languages for weeks and quitting in month two. Pick by what you want to build, then test it in one weekend.

Data Structures Examples You Already Use Every Day
Your music queue, undo button, and contact search are all data structures in disguise. Here's how to spot them and pick the right one for the job.

Object-Oriented vs Functional: Which Thinking Fits You?
Object-oriented thinking groups code by things. Functional thinking groups it by actions. Here's which one to use, and why the debate is mostly noise.
