When your engineering organisation grows from a single team working on a monolith to multiple domain-driven teams, your branching strategy needs to evolve too. At Cashrewards, we lived through this transformation, moving from Gitflow to Trunk-Based Development (TBD) as we scaled. Here's why TBD became our go-to approach and how it changed our development workflow.
Gitflow, introduced by Vincent Driessen in 2010, follows a structured branching model with multiple long-lived branches:
# Typical Gitflow workflow
git checkout develop
git checkout -b feature/new-payment-method
# ... develop feature
git checkout develop
git merge feature/new-payment-method
git checkout -b release/v2.1.0
# ... prepare release
git checkout main
git merge release/v2.1.0
Gitflow Strengths:
Gitflow Pain Points:
TBD is a branching model where developers collaborate on code in a single branch
called "trunk" (usually main
or master
), with minimal branching:
# Typical TBD workflow
git checkout main
git pull origin main
git checkout -b feature/payment-optimization
# ... small, focused changes
git checkout main
git merge feature/payment-optimization
git push origin main
# Deploy immediately or via feature flags
TBD Strengths:
TBD Challenges:
Initially, Cashrewards operated as a single engineering team working on a monolithic application. When I joined as one of 8 engineers during the early startup phase, Gitflow served us well during this phase. Through the IPO journey and beyond, I witnessed firsthand how we grew the engineering team to 40+ engineers organized into domain-focused squads.
Single Team → Monolith → Gitflow
- Clear release cycles
- Coordinated deployments
- Predictable workflow
Our release process looked like this:
As Cashrewards grew, we hit the usual scaling problems:
The warning signs became obvious:
We restructured into domain-driven teams:
Each team needed:
Before (Gitflow):
# Team A develops feature over 2 weeks
git checkout -b feature/loyalty-program
# ... 2 weeks of development
# Integration day: merge conflicts with 3 other features
git checkout develop
git merge feature/loyalty-program
# Conflicts with transaction-refactor, user-profiles, offer-api
After (TBD):
# Daily small commits to main
git checkout -b small-feature/loyalty-points-calculation
# ... 4 hours of focused development
git checkout main
git merge small-feature/loyalty-points-calculation
# Minimal conflicts, immediate integration
With TBD, each team could deploy independently:
Deployment Frequency:
Gitflow Era: 2 deployments/month (coordinated)
TBD Era: 50+ deployments/month (autonomous)
TBD enabled us to decouple deployment from release:
// Feature flag example
if (featureFlags.isEnabled('new-cashback-calculation', user)) {
return calculateCashbackV2(transaction);
} else {
return calculateCashbackV1(transaction);
}
Benefits:
Each domain team gained:
CI/CD Pipeline Enhancement
# GitHub Actions example
name: Continuous Integration
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: npm test
- name: Deploy to Staging
if: github.ref == 'refs/heads/main'
run: npm run deploy:staging
Feature Flag Infrastructure
Branch Policy Changes
# New branch protection rules
- Require pull request reviews (2 reviewers)
- Require status checks to pass
- Require branches to be up to date
- Maximum branch age: 2 days
Developer Training
Gradual Migration
Team Autonomy Implementation
Cultural Reinforcement
Metric | Gitflow Era | TBD Era | Improvement
-----------------------|-------------|-------------|------------
Lead Time | 2-3 weeks | 2-3 days | 83% faster
Deployment Frequency | Bi-weekly | Daily | 14x increase
Mean Time to Recovery | 4-6 hours | 15-30 min | 88% faster
Change Failure Rate | 15% | 5% | 67% reduction
# Good TBD commits
git commit -m "feat: add cashback calculation for grocery category"
git commit -m "fix: handle edge case in payment validation"
git commit -m "refactor: extract merchant API client"
# Each commit should:
- Be deployable
- Include tests
- Have clear intent
- Be reviewable in < 10 minutes
// Gradual rollout pattern
const featureConfig = {
name: 'enhanced-search',
rollout: {
percentage: 25,
userTypes: ['premium'],
geoTargets: ['AU', 'NZ'],
},
};
# Quality pipeline
quality_gates:
- unit_tests: >95% coverage
- integration_tests: all_passing
- security_scan: no_high_vulnerabilities
- performance_test: <500ms_p95
- accessibility_test: wcag_aa_compliant
// Business metrics monitoring
const metrics = {
deploymentFrequency: 'daily',
leadTime: '< 3 days',
mttr: '< 30 minutes',
changeFailureRate: '< 5%',
};
Mistake: Switching all teams simultaneously Solution: Gradual team-by-team adoption with parallel support
Mistake: Manual testing and deployment processes Solution: Invested heavily in CI/CD before switching
Mistake: Accumulating technical debt from old flags Solution: Automated flag cleanup and lifecycle management
Mistake: Reduced visibility into system health Solution: Enhanced observability before migration
TBD at Cashrewards has enabled:
The transition wasn't just about changing our branching strategy—it was about embracing a culture of continuous improvement, team autonomy, and customer-centric development.
Our journey from Gitflow to TBD at Cashrewards shows that the right development workflow can unlock massive improvements in both developer experience and business outcomes. When scaling engineering organisations, the processes that got you here might become bottlenecks—and that's exactly when it's time to evolve.
Have you been through similar scaling challenges in your organisation? What branching strategies have worked best for your team structure? Would love to hear about your experiences.