Founder & Lead Engineer, RAITHub
An offshore team usually ships bugs because nothing stops a bug before release, not because of where the team sits. The fix is a set of gates: a written definition of done, required CI checks on every pull request, a test with every bug fix, an independent QA pass on staging, a release checklist with rollback, and a review of every bug that escapes.
If you would rather have the gates set up and run for you, see how RAITHub would test this below, or the QA as a service overview.
Why does my offshore team keep shipping bugs?
Almost always for process reasons that would cause the same result with a team down the hall. The usual causes:
- Tickets without acceptance criteria. The developer builds what the ticket says, the ticket was vague, and the gap is discovered by a customer.
- Developers test only their own work. The person who wrote the code checks the path they had in mind, not the paths users take.
- No test is required to merge. Tests exist, or do not, but nothing blocks a pull request that breaks them.
- No production-like staging. Code is checked on a laptop with different data, settings and services.
- Slow feedback across time zones. A question asked at the end of one team's day is answered at the start of the other's, so developers guess instead of waiting.
- Incentives to close tickets. If the team is measured on tickets closed, quality is whatever is left at the end of the sprint.
Faster coding makes this worse, not better. The 2025 DORA research on AI-assisted software development describes AI's primary role as "an amplifier, magnifying an organization's existing strengths and weaknesses" (DORA 2025 report). A team without gates that starts writing code faster will ship bugs faster.
What is a QA gate?
A QA gate is a check that must pass before work moves to the next stage, enforced by a tool or a named person rather than by good intentions. The six gates below catch different kinds of bug at different moments.
| Gate | What it blocks | Who owns it | Effort to set up |
|---|---|---|---|
| 1. Definition of done | Work that is "finished" but untested or unclear | Product owner and team lead | An hour to write, weeks to make habit |
| 2. Required CI checks | Merges that fail lint, types, unit or end-to-end tests | The repository settings | Hours if CI exists |
| 3. A test with every bug fix | The same bug returning later | Reviewer of each pull request | No setup; a review rule |
| 4. Independent QA on staging | Bugs on paths the developer did not think of | A tester who did not write the code | Days, if staging needs building |
| 5. Release checklist and rollback | Broken releases with no way back | Release owner | A day to write and rehearse |
| 6. Escape review | The same kind of bug escaping twice | Team lead | 30 minutes per escaped bug |
Gate 1: what should a definition of done include?
A short checklist that every ticket must meet before anyone calls it done. Put it in your pull request template so it appears on every change:
## Definition of done
- [ ] Acceptance criteria in the ticket are met, including the "must refuse" cases
- [ ] Unit or integration tests added for new rules
- [ ] Bug fixes include a test that failed before the fix
- [ ] Tested on staging with production-like data
- [ ] Works for every role that can reach this screen
- [ ] Error states show a clear message and reach error tracking
- [ ] No new console errors; migrations run cleanly from empty
The most important line is the first. Ask for acceptance criteria written as examples ("a manager can approve; a viewer sees the button disabled") before work starts. Most "offshore bugs" are specification gaps.
Gate 2: how do you make CI checks required on every pull request?
Run the checks on every pull request, then make them required in branch protection, so a red check physically blocks the merge. On GitHub, required status checks must succeed before changes can be merged to a protected branch (GitHub protected branches docs). A minimal workflow for a Node and TypeScript project:
name: pr-gates
on:
pull_request:
branches: [main]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npx tsc --noEmit
- run: npm test
- run: npx playwright install --with-deps chromium
- run: npx playwright test --project=chromium
Then, in the repository's branch protection rule for main, require the "checks" job to pass and require at least one approving review. Also turn off direct pushes to main, including for administrators, or the gate has a side door.
Keep the end-to-end layer small at first: the three to seven journeys that make money or hold data. A short, reliable suite that blocks merges is worth more than a long one people learn to ignore. For which journeys to choose, see regression testing on every deploy.
Gate 3: why must every bug fix ship with a test?
Because a bug without a test is a bug that can come back. The rule is simple: the pull request that fixes a bug includes a test that fails without the fix and passes with it. Reviewers reject fixes without one. Over a few months this builds a regression suite shaped exactly like your real failures, which is more useful than any coverage target. If releases are breaking right now, every release breaks something covers the first week of stopping the bleeding.
Gate 4: who should test before a release?
Someone who did not write the code. Developers are good at proving their code does what they intended; an independent tester is good at finding what nobody intended. That tester works on a staging environment with production-like settings and realistic seed data, against the acceptance criteria and with time for exploratory testing.
This is the gate offshore setups most often skip, because the vendor's developers "test their own work". If your vendor has no independent testers, add them, either in-house or as a service such as manual and exploratory testing. Time zones help here: work merged at the end of the developers' day can be tested before they start the next one, with results waiting in a written handoff.
Gate 5: what goes in a release checklist?
A short list run on every release: critical journeys pass on staging, migrations ran cleanly, feature flags are set as planned, monitoring is green, and the rollback is known. Rollback means more than redeploying old code: decide in advance what happens to database changes. The pre-launch QA checklist is a fuller version for a first launch.
Gate 6: what should you do when a bug still escapes?
Hold a short, blameless review for every bug a customer finds: which gate should have caught it, and why it did not. Then change one thing: a new acceptance criterion pattern, a new end-to-end journey, a staging data fix. Track three numbers per release: bugs found by customers, the share of releases that needed a hotfix or rollback (close to what DORA calls change failure rate, "the ratio of deployments that require immediate intervention following a deployment", in its DORA metrics guide), and tickets reopened after "done". If those numbers do not fall within two or three months, the gates are not being enforced.
How do you roll out QA gates without stalling the team?
One gate at a time, in this order: definition of done, required CI checks with the tests you already have, a test with every fix, independent QA, the release checklist, then escape reviews.
Do-it-yourself time estimate: 1 to 2 days to add required CI checks if you already have CI and some tests; 2 to 4 weeks to put all six gates in place alongside normal work, if someone on your side knows GitHub Actions or a similar CI tool. Main risk: flaky tests. If a gate fails at random, people learn to rerun or bypass it. Playwright, for example, labels a test that fails first and passes on retry as "flaky" (Playwright test retries docs); treat those as bugs to fix, using the approach in fixing flaky end-to-end tests.
Is the problem the team or the process?
Give the gates two or three months. If bugs still escape with the gates enforced, you have learned something about the team. If the vendor resists the gates, you have learned something sooner. Signs it is the team: the same kind of bug keeps escaping after reviews, tests are written to pass rather than to check, and nobody can explain how the code deploys. The wider costs of a cheap vendor are covered in the hidden cost of cheap offshore development, and running a remote team well in how to manage an offshore development team. If the codebase itself has become unsafe to change, a code rescue diagnostic comes before more testing.
Buy, build or hire?
| Route | Choose this when | Watch out for |
|---|---|---|
| A tool or SaaS testing platform | Your team will write the tests and only needs CI, device clouds or test runners | Tools do not decide what to test or enforce review rules |
| Freelancers or crowdtesting | You need an independent pass on one release | No memory of the product between releases |
| An in-house QA hire | You can lead QA and want gates owned inside the company | Slow to hire; one person cannot cover security, accessibility and mobile |
| A managed QAaaS team | You want the gates set up and run independently of the developers | Make sure tests live in your repository and CI |
Why RAITHub for QA gates?
- An offshore team that works this way itself. RAITHub is based in Dhaka, and its own builds run their test suites in CI. PropDesk runs 1,024 automated tests, and Sundor Skin runs 530+ and enforces row-level security on 146 PostgreSQL tables.
- Independent of your developers. As a QA service, RAITHub tests work it did not write, which is the point of gate 4.
- Gates in your systems. Workflows, tests and branch rules go into your repository, with IP assigned to you and an NDA as standard.
- Specialist testing on top. Mobile testing on real devices, web application security testing and WCAG 2.2 accessibility audits when releases need them.
When don't you need RAITHub for this?
- When your team can set up the six gates itself. The workflow above and an afternoon of branch settings are a good start.
- When you want to manage testers yourself inside your vendor's team. That is staff augmentation, which RAITHub does not offer.
- When the issue is a certified security attestation. RAITHub's security testing is application-level, not an accredited pentest.
How RAITHub would test this
- Audit: read your repository, CI, branch rules and the last few escaped bugs, and name which gates are missing.
- Gates: add the definition of done, required checks and the first end-to-end journeys in your CI, using your existing tools where they work.
- Independent QA: a staging test pass on each release, with bug reports your developers can act on in their next working day.
- Review: escape reviews and a regular report of customer-found bugs, hotfixes and reopened tickets.
Timeline: the gate setup is a fixed-scope audit with dates agreed before it starts; ongoing QA runs as a monthly plan. You receive: CI workflows, tests and branch rules in your repository, a written gate policy, handover documents, full IP and an NDA. Next step: a free 15-minute audit, then a written fixed quote. RAITHub publishes no rates. For automation details, see QA and test automation.
To get gates in place, request a one-off QA gate audit, or ask about ongoing QA.
Frequently asked questions
Why does my offshore development team ship so many bugs?
Usually because nothing blocks a bug before release: vague acceptance criteria, developers testing their own work, no required tests to merge and no production-like staging. Those are process gaps, and gates close them.
What is a quality gate in CI?
A check, such as lint, type-checking or tests, that must pass before a pull request can merge. It becomes a gate when branch protection makes it required, so a failure blocks the merge.
How long does it take to set up QA gates?
Required CI checks take 1 to 2 days if CI and some tests exist. All six gates take 2 to 4 weeks alongside normal work.
Should the offshore team test its own code?
Developers should write automated tests for their own code. A release still needs a check by someone who did not write it, because authors test the paths they had in mind.
How do I know if the problem is the team rather than the process?
Enforce the gates for two or three months. If the same kinds of bug keep escaping, or the vendor resists the gates, the problem is likely the team.
Can RAITHub act as an independent QA team for another vendor's code?
Yes. RAITHub can test code written by another team, as a monthly plan, a one-off audit or a dedicated team that RAITHub manages.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.