DevelopmentJanuary 20, 2026

Tips and tricks for a scalable CI/CD flow

When you plan a project, you don't always know how big it will end up being. That's why it's essential to follow guidelines that make the development process as smooth as possible. A particularly useful tool for this is a continuous integration and delivery flow, or CI/CD flow.

At the start of a typical development process, before the project is ready to go live, your CI flow looks roughly like this:

During the development phase, steps get added to the process until it ends up looking like the image below. Even so, in some projects you'll see many more steps. Original image.

In this article I'll walk you through a typical CI/CD flow and give you tips for scaling it on larger projects. Keep in mind that these recommendations assume your infrastructure is built on Docker and orchestration tools like Kubernetes.

Define your version control flow

All modern CI tools rely on version control systems, so to keep your CI flow at a good level, you need a well-defined version control flow. If you're looking for ideas, we recommend Git Flow or GitHub Flow. Pick one and adapt your pipeline to your needs.

Recommendations:

  • Run tests on every push, on any branch. This way your developers will catch bugs earlier and code review will go faster.
  • Define which branches you'll use to trigger the Docker image build and deploy it, as shown in the image above.
  • If your releases go through a complicated manual approval process, use tags to ship releases to production.

Specify your environments

Once you have a defined git flow, integrate it with your build logic and adapt it to the number of environments you have. At first, it's normal to deploy everything to production after testing it locally. Later on, you might decide to have development, UAT, and production environments.

Example:

We usually use the master branch to trigger deployment to the development environment. We then merge master into the release branch, which triggers a deployment to UAT, where we let a small group of users try out the new version. If everything works well and the QA team gives the release the green light, we create a tag from the release branch, which triggers the deployment to production.

Set up notifications

It's worth tracking every process in your CI flow through your preferred notification channel. We use Slack on our projects.

  • Create a system notifications channel and configure it to receive alerts from all CI and infrastructure processes.
  • Set up success/failure notifications and alerts when a build starts.

Keep the Docker image simple

A good practice is to avoid passing environment variables into the Docker image. All environment variables should be passed via the docker run command or at the orchestration tool level (Kubernetes, for example). This will also help keep your CI configuration files simple.

Unify your pipeline

Nowadays, more and more companies use microservices architectures; a unified pipeline helps you take advantage of that, because it lets you deploy and configure CI for new microservices much faster. In Drone CI or Travis CI there are plenty of CI environment variables you can use in the pipeline steps (you'll find them in Travis CI environment variables and Drone CI environment variables). Here are some usage examples:

  • To tag a Docker image, you can concatenate the branch and the build number. The result would be something like "master-6". You can also use the git tag version. tags: "${DRONE_COMMIT_BRANCH}-${DRONE_BUILD_NUMBER}"
  • Use the repository name for deployments in your orchestration tools. Here's an example of a Drone CI deployment to a Kubernetes cluster using environment variables.

deploy:
image: peloton/drone-k8s-deployment
deployment_names: '${DRONE_REPO_NAME}'
container_names: '${DRONE_REPO_NAME}'
namespaces: microservices
docker_image: '62673275295.dkr.ecr.eu-west-1.amazonaws.com/${DRONE_REPO_NAME}:${DRONE_COMMIT_BRANCH}-${DRONE_BUILD_NUMBER}'
date_label: deployment.drone.io/date-deployed
secrets: [kubernetes_url, kubernetes_token]

Define a naming convention for Docker images

It's worth defining a strategy for naming Docker images based on the particularities and importance of each environment. For example, in development and UAT environments, where you don't need to be able to roll back, you can use the branch name as the tag, so each new build overwrites the previous image. In production it's better to tag images with the release version number (v1.0.0), which keeps your registry tidier and easier to read by reducing its size.

Use the builder pattern

If you can compile and build something at the CI level, it can be useful to do it as an extra step before including it in the final image. Check out this video to understand it better.

Database migrations as a separate step

Don't run migrations inside the Dockerfile; run them as a separate step. Additional commands, like asset compilation or migrations, should run in separate steps, not when Docker starts up. Also make sure your Docker images start up and become operational as quickly as possible.

Avoid private libraries and submodules

Any extra dependency, like private npm modules or submodules, can cause problems when setting up CI. For example, if you have a submodule and your CI only has default access to your repositories over http with an authorization token, your local machine's git configuration won't work. You'll have to override the submodule, and not every CI tool allows that.

Example of overriding submodules in Drone CI

You'll run into similar problems if you use private npm modules, because you'll need access keys or have the modules already downloaded inside the Docker image.

Conclusion

When setting up CI for a new project, spend some time thinking through and defining naming conventions, possible growth paths, and unifying the build steps. This way you'll be able to deploy new services faster, use these practices as a foundation for new projects, and get new team members up to speed with how the pipeline works sooner.

Tell us about your case

Get in touch