If production keeps finding the same kind of problem, stop calling every incident a surprise. Your live service is telling you where the test approach is weak. The expensive mistake is paying for the lesson and then refusing to learn it.
Also stop assuming every production defect is automatically a testing failure. Sometimes testing missed it. Sometimes the defect was known and somebody released anyway. Sometimes the test environment could never reproduce the production condition. Sometimes nobody owned the end-to-end journey in the first place.
If the same failures keep coming back in different clothes, an independent review can usually show whether the gap is in the testing, the environment, the design, the release decision or some unpleasant combination of all four.
Start with the incidents you have already paid for
Take the recent serious production failures and put them beside the testing that was supposed to protect those areas. For each incident, work out where it could realistically have been caught.
If an existing test ran and passed, look at the test itself. Was the data realistic? Did it check the right outcome or merely prove the page loaded? Was the failure timing-related or dependent on a service the test environment had stubbed out?
If the area was never tested, find out why. Maybe it was consciously accepted. Maybe the environment made it impossible. Maybe two teams each assumed the other one owned it. Those are very different problems and they need different fixes.
Do not turn every incident into one more regression ticket
Adding a test for the exact defect is often sensible. Stopping there is lazy.
If three incidents involved permissions, look at how permissions are tested across the product. If repeated failures involve retries, callbacks or half-completed transactions, look at integration and failure testing. If customers keep finding production-only configuration problems, another functional regression case may do absolutely nothing.
And if the defect was already known before release, do not rewrite history and call it an escape. That is a risk-acceptance or reporting problem. Blaming the test team just teaches everyone to spend the next retrospective defending ticket statuses.
Change the control that actually failed
Sometimes the answer is more testing. Sometimes it is better test data, a more representative environment, stronger automated assertions, clearer ownership or a design that is easier to test.
Sometimes the sensible answer is better monitoring and recovery because the failure is genuinely cheaper to detect in production than to reproduce before every release. That is allowed. The important bit is choosing it deliberately.
Production is the most expensive test environment you own. Try not to pay the same tuition twice.
If production keeps surprising you, get onto us. We can review a sample of the incidents against your current testing and tell you what is actually missing, what is being blamed on testing unfairly and what we would change first.