Practices

Practices are how we turn principles into action. These are proven approaches that high-performing engineering teams use.

Code Quality

Trunk-Based Development

What: Everyone commits to main branch frequently (at least daily).

Why:

  • Reduces merge conflicts
  • Enables continuous integration
  • Smaller, safer changes

How:

  • Use feature flags for unfinished work
  • Short-lived feature branches (hours, not days)
  • Automated tests gate the merge

Code Review

What: Every change is reviewed by another engineer before merging.

Why:

  • Catches bugs early
  • Shares knowledge
  • Maintains standards

Guidelines:

  • Review within 24 hours
  • Focus on correctness, not style (automate style)
  • Approve when “good enough”, not perfect
  • Use review as teaching opportunity

Testing

The Test Pyramid

       /\
      /  \
     / E2E\        <- Few tests, slow, expensive
    /--------\
   /Integration\   <- Medium tests, moderate speed
  /--------------\
 /   Unit Tests   \ <- Many tests, fast, cheap
/-------------------

Unit Tests (70%):

  • Test one function/component in isolation
  • Fast (<100ms per test)
  • Run on every commit

Integration Tests (20%):

  • Test component interactions
  • Test with real dependencies (DB, API)
  • Run in CI pipeline

E2E Tests (10%):

  • Test full user workflows
  • Run against staging/production
  • Run before major releases

Test-Driven Development (TDD)

Red-Green-Refactor Cycle:

  1. Red: Write a failing test
  2. Green: Write minimal code to pass
  3. Refactor: Clean up while tests pass

When to use: Complex logic, unclear requirements, bug fixes.


CI/CD

Continuous Integration

Practices:

  • Commit to main at least daily
  • Automated build on every commit
  • Automated tests run on every PR
  • Fix broken builds immediately

Pipeline Stages:

Build → Unit Test → Integration Test → Security Scan → Merge

Continuous Delivery

Practices:

  • Keep main branch deployable at all times
  • Automated deployment to staging
  • One-click deployment to production
  • Automated smoke tests post-deploy

Pipeline Stages:

Staging Deploy → Smoke Test → Approval → Production Deploy → Verify

Deployment Patterns

Feature Flags:

  • Deploy code without releasing features
  • Enable gradually (canary, % rollout)
  • Instant rollback if issues

Canary Deployment:

  • Deploy to small subset of users
  • Monitor metrics
  • Gradually increase traffic
  • Roll back if anomalies detected

Blue-Green Deployment:

  • Two identical environments
  • Switch traffic instantly
  • Fast rollback (switch back)

Observability

Three Pillars

Logs: Event records

  • Structured logging (JSON)
  • Correlation IDs across services
  • Appropriate log levels

Metrics: Numeric measurements

  • Request rate, latency, errors
  • Business metrics (orders, revenue)
  • System metrics (CPU, memory)

Traces: Request flow

  • End-to-end request tracking
  • Performance bottlenecks
  • Service dependencies

Alerting

Good Alerts:

  • Actionable: There is something to do
  • Specific: Clear what is wrong
  • Timely: Right urgency level

Alert Levels:

  • P0: Page immediately (outage)
  • P1: Page during business hours (degraded)
  • P2: Ticket for next business day (warning)

Security

Secure by Default

Shift Left: Find security issues early

  • Dependency scanning in CI
  • Static Application Security Testing (SAST)
  • Secrets scanning (no secrets in code)

Defense in Depth: Multiple layers of security

  • Authentication and authorization
  • Input validation
  • Encryption at rest and in transit
  • Network segmentation

Security Practices

Secrets Management:

  • Never commit secrets to git
  • Use secret management tools (Vault, AWS Secrets Manager)
  • Rotate secrets regularly
  • Audit secret access

Dependency Management:

  • Scan dependencies for vulnerabilities
  • Keep dependencies updated
  • Pin versions for reproducibility
  • Have an update strategy

Documentation

Documentation Types

README: Getting started

  • What is this project
  • How to run it
  • How to contribute

Architecture Decision Records (ADRs): Why decisions were made

  • Context, decision, consequences
  • One per significant decision
  • Stored in git with code

Runbooks: Operational procedures

  • How to handle common issues
  • Step-by-step instructions
  • Links to relevant dashboards/logs

API Documentation: How to use the service

  • OpenAPI/Swagger specs
  • Example requests/responses
  • Authentication details

Documentation Best Practices

  • Write as you go: Do not wait until the end
  • Close to code: Docs in the same repo
  • Executable docs: Use code snippets that are tested
  • Review docs: Treat docs like code (review, version)

Collaboration

Pair Programming

When to use:

  • Complex problems
  • Knowledge sharing
  • Onboarding

Formats:

  • Driver-Navigator: One types, one thinks
  • Ping-Pong: Switch roles frequently

Mob Programming

Whole team, one keyboard, one problem.

When to use:

  • Complex architectural decisions
  • Knowledge sharing across team
  • Solving sticky problems

Resources