cy.wait can wait on an aliased network request (cy.wait('@alias')) or a fixed number of milliseconds (cy.wait(2000)). Waiting on requests is good; fixed time waits are an anti-pattern that cause flakiness and slowness.
Because Cypress auto-retries commands and assertions, you rarely need to wait manually. When you DO need synchronization — e.g. ensuring an API call completed before asserting — wait on the request alias (cy.wait('@getUsers')), which resolves exactly when the response arrives and also lets you assert on it. A hardcoded cy.wait(3000) is fragile: too short and it flakes on slow runs, too long and it wastes time on every execution. Replace fixed waits with assertions on the resulting UI state or with request aliases.
Replacing cy.wait(5000); cy.get('[data-cy=results]') with cy.wait('@search'); cy.get('[data-cy=results]').should('have.length', 10) makes the test both faster and reliable, keyed to the actual event rather than a guess.
A test uses cy.wait(4000) after clicking Save. Sometimes it still fails, sometimes it's slow. How do you fix it properly?