Continuous Integration and Continuous Deployment (CI/CD) is one of those engineering practices that everyone agrees is important but few teams implement well, especially in the resource-constrained environment of African startups. When every dollar of infrastructure spend matters and engineering time is limited, your CI/CD pipeline needs to be practical, not perfect. This article shares the pipeline design we use at Deveote, which has evolved through real-world use across multiple ventures.
The Minimum Viable Pipeline
Before you invest in a sophisticated multi-stage pipeline with parallel jobs and fancy integrations, you need a minimum viable pipeline that does three things reliably: run your tests, build your application, and deploy to your target environment. If you do not have these three steps automated, nothing else matters. We have seen teams spend weeks configuring elaborate pipeline architectures when they would have been better served by a simple three-step pipeline that actually works.
Stage 1: Lint and Type Check
The first stage of our pipeline runs linting and TypeScript compilation. These checks are fast, typically completing in under two minutes, and they catch the most common issues: formatting inconsistencies, unused imports, type errors, and strict mode violations. By running these checks first, we give developers fast feedback and avoid wasting compute time on builds that would fail due to simple issues.
Stage 2: Test
The second stage runs our test suite. We organize our tests into unit tests, which run in isolation and complete quickly, and integration tests, which require database connections and take longer. Unit tests run on every commit. Integration tests run on pull requests and the main branch. This tiered approach gives us fast feedback for routine changes while ensuring comprehensive coverage for code that is about to be merged or deployed.
Stage 3: Build and Deploy
The third stage builds the application and deploys it to the target environment. For our Next.js applications, this involves running the production build, which catches additional issues like missing environment variables and server-side rendering errors, and deploying the result to Railway. We use separate deployment targets for staging and production, with automatic deployment to staging on every merge to the develop branch and manual promotion to production.
Cost-Effective Pipeline Design
CI/CD compute time costs money, and for early-stage startups, those costs can add up quickly. We employ several strategies to keep pipeline costs manageable. Aggressive caching of dependencies and build artifacts reduces redundant work. Conditional pipeline execution skips stages that are not relevant to the changed files. Branch-specific pipeline configurations run the full pipeline only on branches that matter. We review our pipeline costs monthly and optimize the most expensive stages.
Caching Strategy
Effective caching is the single biggest lever for reducing pipeline costs and duration. We cache node_modules, Next.js build cache, and Prisma generated client between pipeline runs. Our dependency cache is keyed on the lockfile hash, so it is automatically invalidated when dependencies change. The build cache is keyed on the source code hash, so it is invalidated when application code changes. These caches reduce our average pipeline duration from twelve minutes to four minutes.
Environment Management
Managing environment variables across development, staging, and production is a common source of deployment failures. We use a combination of Railway's environment variable management and a local .env.example file that documents every required variable. Our pipeline includes a pre-deployment check that verifies all required environment variables are set in the target environment, preventing deployments that would fail at runtime due to missing configuration.
Monitoring Pipeline Health
A pipeline that is slow, flaky, or frequently failing will be ignored by your team. We track pipeline success rate, average duration, and flakiness metrics. If the success rate drops below 95% or the average duration exceeds ten minutes, we prioritize pipeline maintenance. A reliable, fast pipeline is an investment in your team's velocity, because it removes the friction from the development process and gives developers confidence that their code works correctly.
Conclusion
The best CI/CD pipeline is the one that your team actually uses and trusts. Start with the minimum viable pipeline, optimize for speed and reliability, and add complexity only when the benefits clearly outweigh the costs. In the African startup context, where resources are scarce and speed matters, a practical pipeline that works every time is infinitely more valuable than a sophisticated pipeline that works most of the time.