flashman
← All guides

Regex performance and ReDoS safety guide

Design, test, and bound regular expressions so ambiguous backtracking on untrusted input does not become a production performance incident.

2026-08-26 · 8 min read

  • regex
  • performance
  • security

Regular expressions run inside different engines with different performance guarantees. Backtracking engines are flexible, but an ambiguous pattern can revisit the same input in exponentially many ways. An attacker—or an unusual log line—may then hold a CPU core with only a short string.

Safe regex work combines pattern design, adversarial tests, input bounds, and runtime controls. No single syntax rule catches every problematic expression.

Recognize ambiguous repetition

Nested quantifiers such as (a+)+ are a familiar warning, but overlapping alternatives and repeated optional groups can behave similarly. The slowest input is often a near-match that repeats the ambiguous section and fails at the end.

  • Question whether two alternatives can consume the same prefix.
  • Avoid repeating groups that can match empty strings.
  • Make character classes as specific as the data contract allows.
  • Anchor full-string validation when partial matching is not intended.

Measure growth with adversarial fixtures

Test a synthetic non-match at several lengths and record elapsed time. Linear or gently increasing time is expected; rapid multiplication suggests dangerous backtracking. Run tests in the same engine and flags used in production because browser, Java, .NET, Python, and RE2-family behavior differs.

Keep fixtures free of customer data. The shape of repeated characters matters; real production values do not.

Refactor for a smaller search space

Split complex validation into multiple checks, replace broad wildcards with bounded classes, or parse structured formats with a real parser. Engine-specific atomic groups and possessive quantifiers can remove backtracking paths, but only when the target runtime supports them.

  • Prefer explicit maximum lengths over unbounded repetition.
  • Use a linear-time engine for untrusted input where practical.
  • Apply request size limits before regex evaluation.
  • Add timeouts or worker isolation when the runtime supports them.

Operate regex as production code

Review pattern changes with examples, benchmarks, and negative cases. Monitor slow request or pipeline stages, and log the pattern identifier and input length rather than sensitive input.

Use Flashman's regex tester for synthetic cases, diff tool to review pattern revisions, timestamp converter to align latency events, and JSON formatter for structured logs. Browser tests are useful feedback, but production-engine tests remain the source of truth.

Try these tools