The cases come from error analysis, the step where you read real traces and named the ways your system fails. Pull cases for each named failure mode, add a block of ordinary everyday requests, and add a small block of adversarial inputs, meaning inputs designed to trick the system. The everyday block is not padding. It catches a change that fixes an edge case but breaks the normal request.
Do not fill the set with a random sample of traffic. Most traffic is the easy path, so a failure that hits 1 percent of requests shows up about twice in 200 random rows. If a change breaks it completely, the overall score moves by about one point and disappears into normal run-to-run noise. A stratified set fixes the count on purpose, for example 20 cases per failure mode, so a break in any mode moves its own bucket sharply.
Size follows coverage. A few dozen to a few hundred well-chosen cases usually beat thousands of random ones, because every expected answer needs a person to stand behind it, and 150 answers you trust are sharper than 3,000 nobody checked. Size still limits what you can detect. In a simulation of 4,000 eval runs from an 80 percent baseline, a real 5-point gain was caught 15 percent of the time with 100 cases and about 83 percent of the time with 1,000, while a 2-point gain never reached 80 percent detection even at 5,000.