--maxWorkers option to specify the number of workers to use.
--workers option to specify the number of workers to use.pytest-xdist plugin.
An important thing to keep in mind before sharding your tests with GitHub Actions is - all the steps inside the job are run again for each shard. This includes dependency installs, fetching third party actions, etc. For example, as stated earlier in the Playwright setup, we need to install the browsers for each shard.
Steps like these could add significant overhead and the performance gain might not be worth it or even inexistent. In worst cases, it might even increase the overall run time. It makes sense to benchmark your tests before and after sharding to see the benefits. Usually, large test suites with long run times benefit the most from sharding.
timeout-minutes, a forgotten debug session will continue burning minutes until it hits that limit.
s3 backend does not go through this container but is instead directly transferred from s3 to the docker process. This is beneficial as it avoids egress fees in many scenarios.
actions/cache action directly to cache the relevant directories.
node_modules is not recommended by GitHub as it fails across Node versions and doesn't work well with npm ci.
npm, yarn, or pnpm). You can get the cache directory by running npm config get cache or yarn cache dir. Learn more here.
pip by running pip cache dir and for poetry by running poetry config cache-dir. Learn more here
vendor directory instead of downloading from the network or restoring from cache. In such cases, caching the Go modules directory may not be necessary.
ruby/setup-ruby action as shown above.
NUGET_PACKAGES is also recommended for caching the NuGet packages directory instead of the global cache directory since there might be some huge packages pre-installed.
main.
Track: total minutes/spend, median run time for critical workflows, queue time, artifact GB.
max-parallel, then A/B compare durations and queue times before switching your default runner.
See: jest.retryTimes
```yaml # Jest run: npx jest --maxWorkers=50% # consider also: jest.retryTimes() ```See: pytest-rerunfailures
```bash # Pytest example pytest -q --maxfail=1 # fail fast pytest --reruns 2 --only-rerun "AssertionError" ```Compute
Networking
Storage/Registry
Terraform examples
References: EC2 pricing, Spot, NAT pricing, VPC endpoints, S3 pricing
Compute
Networking
Storage/Registry
Examples
References: Compute pricing, Spot/Preemptible, Private Google Access, Cloud NAT pricing, Artifact Registry
Compute
Networking
Storage/Registry
Examples
References: VM pricing, Spot, NAT pricing, Private Endpoints, ACR
max-parallel to contain burst costs.
- Spot-friendly pipelines: persist caches early, checkpoint long jobs to resume.
```mermaid
flowchart TD
S["Non-critical job?"] -->|Yes| Off["Schedule off-peak"]
S -->|No| Now["Run now"]
Off --> Spot["Prefer Spot/Preemptible"]
Now --> Guard["Apply concurrency + timeouts"]
```
### Workflow-level cost controls
- Conditional execution (paths/paths-ignore), concurrency cancellation, timeouts, matrix throttling.
- Keep storage cheap: compress artifacts, shorten retention, upload minimal logs.
---
## Cost comparison and ROI
| Monthly workload | Hosted Linux x64 | Self-hosted on-demand | Self-hosted spot | Notes |
| --- | --- | --- | --- | --- |
| 10,000 min | $$ | $ | $ | Depends on instance type, cache hits, NAT/egress |
| 100,000 min | $$$ | $$ | $-$$ | Maintenance overhead more salient |
actions-runner-controller but with none of the operational complexity. WarpBuild runners are also more cost effective than ARC runners, with a ~41% cost saving.