1 min read
Shipping a hundred pull requests a day
Sovica Engineering Platform
We merged 1,903 pull requests into Sovica between 10 and 31 October 2026. On a busy day that is well over a hundred. Most of them are written by parallel builder lanes, each working on its own feature package. This is how we keep main green at that pace.
Lanes and blocks
Each lane claims one package of work and works on its own branch. Database migrations are plain SQL files numbered in order, so each lane gets its own block of 50 migration numbers. Two lanes can never write migration 3620 at the same time, and a merged migration is never edited: a checksum guard refuses it.
Trains instead of queues
Running the full integration and end-to-end suites on every pull request would cost hours of CI per change. Instead, ready pull requests board a train: one branch that merges several of them, gets the full gate once, and lands on main with a merge commit so every car’s head commit is in main.
- Every push to a lane runs format, lint, build, typecheck and unit tests, then an end-to-end smoke set of about 50 tests.
- A train adds the integration suite in three shards.
- The full end-to-end suite runs at least once every five merged pull requests, and before any release.
Conflicts are resolved once, on the train, while each diff is still small. A car whose only conflict is the lockfile gets it regenerated; anything else drops the car back to its lane.
A ready check that says no
Lanes merge their own green pull requests through one command, merge:ready. It refuses a pull request whose changed files fail Prettier (every post-merge revert we had in our first weeks was an unformatted file), and it refuses one whose work checklist is not ticked with evidence. A pre-commit hook formats staged files, so the check rarely fires.
What we learned
Speed came from making the safe path the fast path: small branches, batched gates, and checks that block in seconds rather than reviews that block for hours.