All services

CI/CD

Deploy at night. Never on a Friday.

Putting releases into the night and avoiding Fridays is not a scheduling decision, it is a trust problem: the path that carries your code into production is the least reviewed software in the building. It has grown over years, its author has left, and it holds access keys nobody counts any more. All of that can be fixed, and without changing tools.

One artefact, every stageOIDC instead of keysRollback rehearsedHanded to your team
What you get
  • A pipeline you can read in five minutes: one build, one artefact, three stages
  • Access through short-lived tokens instead of stored long-lived keys
  • Third-party actions pinned to a commit SHA, artefact provenance verifiable
  • A way back that has been rehearsed once, with your team, on a real service
  • Runtime and cost of the path measured rather than estimated
  • Handover: your team changes the pipeline afterwards without me
Scope & working together

Assessment and target picture as a bounded two to four week engagement, implementation afterwards according to scope. Operations and on-call stay with your team, which is why the handover is part of the work.

Remote from Germany. Straight with me, no agency in between.

The starting point

The pipeline is software. It is simply not treated as such.

In almost every grown system the delivery path is the part with the weakest rules. No review, no tests, no versioning of its steps, yet access to production and to every credential needed there. The result is one build per stage instead of one artefact for all of them: what was tested in staging is not what runs in production, it is a second build with the same ingredients at a different moment. That is exactly why nobody wants to deploy on a Friday.

The second point is a security problem that looks like convenience: stored long-lived keys. An AWS access key in the pipeline secret store is valid until somebody rotates it, and nobody rotates it. What follows from that has been demonstrated repeatedly over the past eighteen months. In March 2025 attackers repointed the version tags of a widely used action (tj-actions/changed-files, more than 23,000 repositories, CVE-2025-30066) at a commit of their own; it read secrets out of the runner memory and wrote them into the logs, which on public projects anyone can read. In 2026 the same pattern ran twice through npm packages: hijacked release workflows, tokens taken from runner memory, carried onward through the pipelines of the next projects. Not one of those attacks needed a flaw in your code.

The third point is the way back. Almost every pipeline has a documented rollback and almost none has a rehearsed one. The difference shows up at the database: a migration that renames a column makes rolling the application back impossible, whatever the runbook says. Anyone who genuinely wants the way back builds schema changes in two steps and rehearses once what happens when it is needed. After that a release is a routine rather than an event.

Does any of this sound familiar?
  • Deployments happen at night or at the weekend because they are too risky during the day.
  • The pipeline has an author, and that person has left the company.
  • The secret store holds access keys and nobody knows what they are valid for.
  • A run takes forty minutes and half of it builds the same thing twice.
  • The rollback is described but has never been executed.
  • Third-party actions sit on @v3 and nobody has looked at what is inside.

What I do

What happens along the way

01

Build once, then only promote

Build onceArtefact registryPromotion

Exactly one artefact is produced per commit, a container image or a package, and that same artefact moves through staging and production. What ships is therefore what was tested, not something with the same ingredients. The stages differ only in configuration and approval, never in content.

02

Access without long-lived keys

OIDCIAM rolesEnvironments

The pipeline obtains its permissions at runtime through OIDC: GitHub Actions or GitLab CI exchange a short-lived token for an AWS role, bound to repository, branch and environment. There is no key left to steal, and the rights of the production stage no longer hang on a value in a secret store.

03

Nail down the supply chain

SHA pinningAttestationsDependabot / Renovate

Third-party actions are pinned to a full commit SHA rather than to a tag that can be repointed. That recommendation comes from GitHub itself and since August 2025 it can be enforced as an organization policy. Alongside it: artefact attestations, so it stays verifiable which run an image came from, and dependency updates as pull requests rather than surprises.

04

Rehearse the way back

Blue/GreenCanaryTwo-step migrations

Blue/green or canary, whichever the application allows, together with schema changes in two steps: roll out additively, then the application, then clean up. After that the way back is walked once for real, on a live service, with your team present. An unrehearsed rollback is a claim.

05

Runtime and cost of the path

CachingParallelismRunner choice

We measure where the minutes actually go: duplicate build steps, caches that save nothing, tests without parallelism, container images with no layer discipline. Self-hosted runners come after that and only when they pay off. They trade a bill for operational work, and that is not always the better trade.

06

Handover, so it belongs to you

As codeRunbookHandover

The pipeline lives as code in the repository, with comments at the places where somebody will later have to make a decision. Along with it a runbook for the way back, a note on approvals and ownership, and a handover session. Afterwards your team changes the path without asking me.

When was your last deployment on a Friday afternoon?

Tell me what your delivery path looks like today and what went wrong during the last release. You get an assessment before you commission anything.

How it runs

How this works

Four steps, and after the second one the target picture and the effort are on the table. No step assumes you will commission the next one.

STEP 01

Assessment

I read the pipeline, the approval paths and the incident history of recent releases. The result is a list: where long-lived keys are in use, which steps build twice, which actions are unpinned, where the way back is missing.

STEP 02

Target picture and order of work

Which stages there should be, who approves, how the artefact is promoted, how a rollback happens. Plus the order by benefit: what gets done first is whatever makes the next release calmer.

STEP 03

Implementation on a real service

Not on a sample project but on a service that actually ships, small enough to start with and real enough to count as proof. The old path stays in place until the new one has run twice without incident.

STEP 04

Rehearsal and handover

A rehearsed rollback, one run with your team watching, then the handover. After that you apply the pattern to the remaining services, without me if you prefer.

The outcome

What is different afterwards

Releases before lunch

Once the way back is rehearsed and one artefact moves through every stage, the timing stops mattering. That is the real gain, and you can measure it in the mood of the team.

No keys left to steal

What does not exist cannot leak. With OIDC the secret store holds no cloud credentials any more, only short-lived tokens bound to repository and environment.

The next supply chain attack misses you

Pinned actions, verifiable image provenance and secrets with a narrow scope. The attacks of 2025 and 2026 would have found nothing in a path built this way.

Shorter lead time

One build instead of three, caches that actually hit, tests in parallel. That saves minutes per run and hours per week, and it lowers the bill for compute along with it.

Technologies I use

What I work with

CI systems
  • GitHub Actions
  • GitLab CI
  • AWS CodePipeline
Identity
  • OIDC
  • IAM roles
  • GitHub Environments
  • GitLab ID tokens
Artefacts
  • Docker
  • Amazon ECR
  • GHCR
  • Composer
  • Artifact attestations
Infrastructure
  • Terraform
  • AWS CDK
  • ECS Fargate
  • Lambda
Rollout
  • Blue/Green
  • Canary
  • AWS CodeDeploy
  • Feature flags
Checks
  • PHPUnit
  • Go Test
  • PHPStan
  • Trivy
  • Playwright
Dependencies
  • Dependabot
  • Renovate
  • SHA pinning
  • SBOM
Measurement
  • Runtime per step
  • Lead time
  • Change failure rate
Tim Rutte, Cloud & Software Architect

Who you are talking to

Directly with me as a freelancer. No agency in between.

I am Tim Rutte. More than 20 years in software development, and the riskiest deployments were never the frequent ones. They were the rare ones nobody had practised any more. You talk to the person who touches your code, from the first call to the handover.

  • 20+years in software development
  • 50+successful projects
  • 2003working remotely since then
More about me

Common questions

Common questions about deployment pipelines

GitHub Actions or GitLab CI, which do you recommend?

Whichever already hosts your code. Both systems can do everything described here: short-lived tokens through OIDC, environments with approvals, matrix runs, self-hosted runners. The difference between them is YAML syntax and billing, and that is small next to the difference between a reviewed path and a grown one. Which is why this page is named after the work rather than after a tool: switching is rarely the answer, and when it is, the reason lies somewhere other than the pipeline.

We want to migrate from GitLab CI to GitHub Actions. Do you do that?

Yes, but you should not pay for the mechanical part: GitHub ships a free tool for it, the Actions Importer. It translates GitLab pipelines into workflows, can do so as a dry run, and even forecasts future usage. What it cannot do is the rest, and the rest is the work: reordering secrets, granting permissions through OIDC instead of stored keys, rebuilding approvals and four-eyes rules, replacing or relocating self-hosted runners, and proving at the end that the way back still functions. If all you need is the translation, I will point you at the tool and not write an invoice.

What does building the pipeline cost?

Billed by time spent, with the assessment and target picture as a bounded two to four week engagement. I name the order of magnitude in the first conversation, once it is clear how many services ship and what the approvals look like. Unlike the upgrade pages there is deliberately no fixed-price package here: the work between "we have no pipeline" and "we have one but nobody trusts it" is too different to press into one delivery.

Will you operate the pipeline afterwards?

No, and that is a decision rather than a capacity question. A delivery path operated by an outsider puts exactly the knowledge outside the company that is needed inside it on a Friday evening. I build it, rehearse it with you and hand it over. What remains afterwards are questions, not responsibilities.

Do we need self-hosted runners?

Usually not at the start. They are right when runs need to reach into a private network, when you need large caches or particular hardware, or when usage is high enough that operating them pays off. They are wrong as a first answer to long runtimes: those almost always come from duplicate build steps and ineffective caches, and your own runner simply takes the same detour on your own hardware. On top of that a self-hosted runner sharpens the security question, because it holds credentials and outlives the run.

How much downtime does the rebuild cost?

None. The new path is built next to the old one and runs twice on a real service before anything is switched over. Until then the old way is the valid one. This is the same approach as any migration: two paths in parallel, comparison, then decommissioning.

We have approvals and a four-eyes rule from audit. Does that fit?

Yes, and it usually ends up better documented than before. Approvals live in both systems as environments with reviewers, and because every run is logged the evidence chain appears on its own: who approved what, which artefact went to production, which commit it came from. Artefact attestations make that last point cryptographically verifiable rather than merely asserted.

Is this not part of backend development?

In a project with me, yes. There tests, pipeline and infrastructure are built along the way rather than afterwards. This page is for the other case: the system runs, the team is in place, and the path into production is the only part nobody trusts. That does not call for backend development, it calls for two to four weeks in exactly that spot.