- Use version 2.1 for all configs to enable orbs, reusable commands, executors, and pipeline parameters
- Name jobs and workflows descriptively: build-and-test, deploy-staging, nightly-integration — visible in the CircleCI dashboard
- Define reusable executors at the top of config.yml for consistent environments across jobs
- Extract repeated step sequences into reusable commands with parameters for DRY configuration
- Set resource_class explicitly on every job to control compute costs and match workload requirements
- Always use version: 2.1 — it unlocks orbs, reusable commands, executors, pipeline parameters, and conditional workflows
- Name jobs descriptively: build, lint, test-unit, test-e2e, deploy-staging, deploy-production — names appear in the CircleCI UI and status checks
- Define reusable executors at config top-level: share Docker image, resource_class, and environment variables across jobs
- Extract repeated steps into commands with parameters: checkout + install + cache restore as a single reusable command
- Set resource_class on every job: small for lint, medium for tests, large/xlarge for builds and E2E suites
- Use workflow orchestration with requires: to define job dependencies — parallelize independent jobs (lint | test | security-scan)
- Define pipeline parameters for dynamic behavior: environment selection, skip-deploy flags, manual trigger inputs
- Use YAML anchors or commands for shared environment variables and common setup steps across jobs
- Organize complex configs with dynamic configuration (setup workflows) to generate config based on changed files
- Set no_output_timeout on long-running steps to prevent premature kills — default is 10 minutes
- Use when/unless conditions on steps and jobs to skip unnecessary work based on pipeline parameters or branch