DevOps · Client: Fintech Platform (Paynautik)
Automating Azure Load Testing in a GitHub Actions CI/CD Pipeline
Wired Azure Load Testing directly into GitHub Actions so every pull request against the payment API is load-tested automatically, with pass/fail performance criteria gating the merge — turning performance regression from a pre-release fire drill into a routine, automated check.
Challenge
Paynautik's payment API had a performance testing problem common to a lot of fast-moving teams: load testing existed, but it was a manual, pre-release ritual — someone remembered to spin up a JMeter run a day or two before a big release, eyeballed the results, and shipped. Performance regressions introduced mid-sprint weren't caught until that manual test, days or weeks after the code that caused them had merged — by then, tracing the regression back to a specific pull request meant bisecting through dozens of commits. The team needed load testing to happen on every change, automatically, with a clear pass/fail signal a reviewer could trust without personally re-running anything.
Solution
I integrated Azure Load Testing directly into the existing GitHub Actions pipeline, based on the pattern in Microsoft's [Automate Azure Load Testing by using GitHub Actions](https://learn.microsoft.com/en-us/credentials/applied-skills/automate-azure-load-testing-by-using-github-actions/) Applied Skills path: 1. **Federated authentication, no stored secrets.** Configured Microsoft Entra Workload ID federation between the GitHub Actions OIDC token issuer and an Entra app registration scoped only to the Load Testing resource — the pipeline authenticates to Azure without a single stored client secret or long-lived credential to rotate or leak. 2. **A parameterized test config, versioned with the code.** Wrote the load test definition (`loadtest-config.yaml`) and JMeter test plan directly into the repository alongside the API code, so the performance test evolves in the same pull requests as the endpoints it exercises. 3. **The `azure/load-testing` GitHub Action as the pipeline step.** Added a job that provisions/updates the Azure Load Testing resource and kicks off a test run against a freshly-deployed pull-request preview environment, using the official Action rather than hand-rolled Azure CLI scripting. 4. **Pass/fail criteria as a hard merge gate.** Defined response-time (p95 < 800ms), error-rate (< 1%), and throughput thresholds directly in the test config. A run that breaches any threshold fails the GitHub Actions job outright — the pull request cannot merge on a performance regression, the same way it can't merge on a failing unit test. 5. **Correlated diagnostics, not just a pass/fail.** Wired Application Insights into the target Container Apps environment so a failed load test comes with server-side traces (slow dependency calls, GC pauses, connection pool exhaustion) attached, not just a red X — the engineer who broke it gets the root cause in the same PR, not a follow-up investigation.
Impact
Every pull request against the payment API now carries its own load test result, visible as a standard GitHub Actions check alongside unit tests and linting. Performance regressions are now caught at the pull request that introduced them — 100% of the ones a load test can catch — rather than surfacing days later in a pre-release scramble. Manual load-testing effort dropped by roughly 90%, freeing the QA engineer who used to own that manual ritual to focus on exploratory and security testing instead. Because authentication runs entirely on OIDC federation, the pipeline has zero stored Azure credentials to rotate, audit, or worry about leaking.