Engine flavor matters
JavaScript uses its own flavor (no free-spacing `(?x)` mode, different Unicode property support by version). Python, Java, and Go each diverge. Copy-paste without checking the target engine is the top cause of “works in regex101, fails in prod.”
Global flag state in JS (`/g`) mutates `lastIndex` — classic bug in loops. Sticky (`y`) and dotAll (`s`) change behavior in subtle ways.
Validate with the same engine you ship. Browser tool for frontend; Node script for backend; do not cross-test PCRE-only features in JS.
Safety and readability
Catastrophic backtracking shows up in nested quantifiers like `(a+)+`. Prefer possessive-style rewrites, atomic groups where supported, or parse with a real parser for nested structures (HTML, JSON).
Comment your intent above the pattern, not inside it (unless your engine supports verbose mode). Future you will not remember what group 3 was for.
The Regex Tester on DroidXP highlights matches live in the browser — tweak pattern and sample text without redeploying. We use it before pasting into validators and CI grep steps.
Patterns we actually reuse
Email and URL validation: prefer well-tested libraries or platform validators over heroic regex. If you must regex, document false positives you accept.
Slugify: lowercase, strip non-alphanumerics, collapse dashes — simple and good enough for blog URLs.
Log parsing: anchor on stable tokens, use non-greedy quantifiers, test on production-sized lines not three-char samples.
Shipping regex responsibly
Add fixture tests with both matching and non-matching strings, including unicode and empty input.
Set match timeouts where your runtime allows (server-side). Reject user-supplied patterns in multi-tenant tools unless sandboxed.
When readability suffers, split into named steps or a tiny parser — regex is a scalpel, not a hammer for every string problem.