Engineering8 min read

CI/CD That Actually Ships: The Pipeline We Put on Every Project

By Niraj Jha ·

Co-Founder & CTO · Last updated

Key takeaways

  • A pipeline's job is to make shipping so safe and boring that nobody is afraid to deploy - the pipeline catches problems, not the user.
  • Shift detection as far left as possible: a type error in the editor costs nothing, the same error in production costs a support ticket and some trust.
  • Keep CI fast or developers route around it - cache aggressively, parallelise jobs, and treat pipeline speed as a feature.
  • Preview deployments on every PR collapse the feedback loop by letting people use the actual change before it merges.
  • Automatic production deploys are only safe with a fast, well-rehearsed rollback - build the rollback before the automation.

A deployment pipeline has exactly one job: make shipping so safe and so boring that nobody is afraid to do it. When deploying is a tense, manual ritual reserved for Friday afternoons, a team ships rarely, batches up risk, and dreads the moment a release goes wrong. When deploying is a non-event that happens many times a day, the whole psychology changes.

This is the CI/CD setup we put on every project, why each piece earns its place, and the principle that holds it all together: the pipeline should catch problems, not the user.

The principle: shift the failure left

Every bug is cheapest to catch at the moment it is written and most expensive to catch in production. The entire design of a good pipeline is about moving the point of detection as early - as far "left" - as possible. A type error caught in the editor costs nothing. The same error caught by a user costs a support ticket, a hotfix, and some trust.

So we build the pipeline as a series of gates, each one cheaper and faster than the failure it prevents.

StageCatchesTime to run
Editor / pre-commitFormatting, lint, obvious type errorsInstant
CI: typecheck + lintType errors, style violationsSeconds to a minute
CI: testsBroken logic, regressions1-5 minutes
CI: buildBuild-time and import errors1-3 minutes
Preview deployVisual and integration issuesOn every PR
Production deployNothing, ideallyAutomatic on merge

What runs on every pull request

Nothing reaches the main branch without passing through CI. On every pull request, automatically:

  • Type checking. With a fully typed stack, the compiler is the cheapest and most thorough reviewer you have. A green typecheck rules out a huge class of bugs for free.
  • Linting and formatting. Enforced by the machine, not by reviewers. Humans should review logic, not argue about whitespace.
  • The test suite. Focused on the core workflows - the loops that, if broken, mean the product does not work. We do not chase a coverage number; we cover the parts that matter.
  • A production build. Plenty of errors only appear at build time. Building in CI catches them before merge instead of during deploy.

Make CI fast or developers will route around it. If the pipeline takes twenty minutes, people batch up changes, push less often, and the feedback loop you built collapses. Cache aggressively, run jobs in parallel, and treat pipeline speed as a feature, not an afterthought.

Preview deployments change everything

This is the piece teams most often skip and most regret skipping. Every pull request gets its own live, deployed preview environment with a unique URL. Reviewers, designers, and the client click through the actual change running on real infrastructure - not a screenshot, not a description, not the reviewer's imagination.

Preview deploys collapse the feedback loop. A misunderstanding that would otherwise be discovered after launch gets caught in code review, because someone actually used the feature. For an agency, this is also how we keep clients in the loop: they see the working change before it merges, on a link they can open on their phone.

Make production deploys a non-event

When everything passes CI and the PR is merged, deploying to production should happen automatically, with no human ceremony. The drama is removed precisely because all the checking already happened. Merging is the decision; deploying is the consequence.

Two things make automatic production deploys safe rather than reckless:

  • Database migrations that are safe under load. Schema changes run as part of the deploy, written to be online and reversible so a migration never locks a production table or strands the app between versions.
  • A fast, obvious rollback. When something does slip through, recovery has to be a single, well-rehearsed action - redeploy the previous version, flip a flag - not a frantic investigation. The question in an incident is "how do we get back to safe," and the answer must be instant.

Automatic deploys without a rollback plan are not confidence - they are gambling. The willingness to deploy on every merge is earned by knowing you can undo it in seconds. Build the rollback before you build the automation, not after your first bad night.

Observability closes the loop

The pipeline's job ends at deploy; observability tells you whether the deploy was actually fine. Error tracking, uptime monitoring, and basic performance metrics turn "I think it is working" into "I can see it is working." When an error rate spikes right after a deploy, you know which change to roll back. Without this, production is a black box and every report comes from an annoyed user instead of a dashboard.

Why this is worth the setup cost

Standing up this pipeline takes real time at the start of a project, and it is tempting to skip it when you are racing to ship. We do not, because the pipeline is what lets us ship fast and keep shipping fast. It is the machinery that makes "deploy continuously from week two" possible instead of terrifying.

A team with a good pipeline ships small changes constantly, catches problems while they are cheap, and recovers from mistakes in seconds. A team without one ships rarely, batches risk, and treats every release as an event. The difference is not talent or effort. It is whether the boring, automated safety net exists - and building that net is one of the first things we do on every project.

Frequently asked questions

What should run on every pull request?
Type checking, linting and formatting, the test suite focused on core workflows, and a full production build. Nothing reaches the main branch without passing these gates, each one cheaper and faster than the failure it prevents.
Why are preview deployments worth setting up?
They give every pull request a live, deployed environment with a unique URL, so reviewers, designers, and clients click through the actual change on real infrastructure instead of a screenshot or a description. Misunderstandings get caught in review instead of after launch.
Is it safe to deploy to production automatically on every merge?
Yes, but only with two things in place: database migrations that are online and reversible, and a fast, obvious rollback. The willingness to deploy on every merge is earned by knowing you can undo it in seconds - build the rollback before the automation.
How fast should a CI pipeline be?
Fast enough that developers do not route around it. If the pipeline takes twenty minutes, people batch changes and push less often, and the feedback loop collapses. Cache aggressively, run jobs in parallel, and treat speed as a feature, not an afterthought.

Have a product to build?

Shunya ships production software - web, mobile, AI, and cloud - with one team that owns the whole stack from concept to launch. Tell us what you want to build.

Niraj Jha

Written by

Niraj Jha

Co-Founder & CTO

Co-Founder & CTO of Shunya Tech. Full-stack architect who sets the engineering culture and technical standards behind every product we ship - from database design to production delivery on Next.js, tRPC, and Prisma.

Last updated