Development Flow - ivelum/job GitHub Wiki

We have several teams working on different projects, and their processes can vary. That said, we have a preferred approach, described below, that we strive to maintain across the board.

Full-stack

Most of our developer roles are full-stack, meaning they cover not just back-end and front-end work, but also testing and deploying to production. We adopted this approach many years ago, and today nearly all of our developers work this way.

In our experience, it significantly speeds up development and improves code quality. It also keeps teams small and flexible and simplifies project management. Read more about this in our blog post.

True DevOps

Originally, the term DevOps referred to a team structure in which the roles of "dev" and "ops" were merged rather than kept separate. When the DevOps movement took off in the mid-2010s, many companies that tried to adopt this approach ran into serious difficulties. Combining "dev" and "ops" demanded a radical rethinking of how teams operated, and not everyone was prepared for it. A rather ingenious workaround emerged, however: redefining DevOps itself. The term came to denote a dedicated role—essentially a system administrator who knew Kubernetes and could set up CI/CD pipelines. This stripped the concept of nearly all its original meaning, but at least companies could now claim they had "implemented DevOps" without disrupting anything.

We practice DevOps in its original sense: not as a specific role on a team, but as the absence of one. There is no separation between "dev" and "ops": every developer has the skills to understand how production and CI/CD work, and can configure them, optimize them, and troubleshoot problems as they arise.

Product Strategy

Every team needs a clear product owner, whether that's a product manager, a customer representative, or a startup founder. This person sets the business-level goals, defining what we want to achieve and why. Developers then propose solutions for how to get there. The best ideas emerge through collaboration between business and technical perspectives, when everyone brings their expertise to the table.

Direct and Open Communication

We encourage direct communication between the person assigning a task and the person carrying it out, without intermediaries like managers or analysts. We'd rather not play a game of telephone, so we make sure every developer has the chance to talk directly with whoever assigned the work. We do have team leads and product managers, but they serve as discussion moderators rather than relay stations.

We also try to keep most project-related communication out in the open, where the whole team can see it—whether in team chats, task trackers, or meetings that everyone is invited to. Open communication helps information spread quickly across the team, surfaces misunderstandings sooner, and makes it easier to land on the best solutions.

A cautious approach to estimates

Wherever possible, we try to avoid blanket task estimates; though we recognize this isn't always feasible. Estimates tend to slow the team down and can create misleading expectations among everyone involved in the project. For a deeper dive, check out the video on our channel:

Continuous Delivery

A mature development process makes it possible to deploy to production multiple times a day without downtime or disruption for users. Several conditions need to be in place for this to work:

  • Ubiquitous automation. We automate production deployments through CI/CD and manage infrastructure as code with Terraform and CloudFormation.
  • Zero-downtime deployment. Well-configured automation eliminates most causes of downtime during deployment, though some cases still require developer attention. See our blog post and video for a detailed breakdown.
  • A culture of quality. Automated testing, manual testing, code reviews, and beta testing with end users all work together to boost confidence in product stability.
  • Production monitoring. On nearly all our projects, we rely on Sentry to track production errors. Depending on the project, we also use DataDog, New Relic, CloudWatch, or similar tools to monitor application performance and overall system health. Detecting anomalies early helps us reduce or entirely prevent user impact when issues arise in production.

Testing Approach

Many years ago, we used to have dedicated QA, but our approach has evolved. We've found that product quality improves significantly when developers do their own testing. We're not alone in this. For example, Google reached the same conclusion. See their book How Google Tests Software.

As a result, we no longer have a dedicated QA team and don't hire for those roles. Our developers handle both manual and automated testing, conduct code reviews, keep technical debt under control, rely on automated production monitoring, and write postmortems when things go wrong.

Trunk-based development

Rather than maintaining multiple long-lived branches, we prefer to work primarily on a single main branch. We've found this to be the most effective approach for continuous delivery and frequent production releases. It also encourages small, incremental updates instead of merging large chunks of functionality at once, which reduces the risk of bugs reaching production and makes issues easier and faster to diagnose when they do arise.

Instead of relying on feature branches, we use feature toggles. These allow us to merge unfinished work into the main branch and showcase in-development features directly in production, eliminating the need for staging or other demo environments.

Staging isn't necessary

Staging slows down development, breaks Continuous Delivery, and, counterintuitively, degrades overall product quality, all while adding the overhead of maintaining the staging environment itself. For a deeper look at this, check out the following video on our channel:

Reviews aren't just about Pull Requests

Pull requests may be the most common way to conduct code reviews, but they're far from the only one. There are at least two alternatives:

  • Asynchronous non-blocking reviews — the code is merged into the main branch first, and someone else reviews it afterward.
  • Video call reviews — the author and reviewer hop on a call and walk through the code together.

Each approach has its own strengths and weaknesses, so depending on the team and the situation, we use different methods or combinations of them.