Adopting tools without a method can compromise the security, reliability and maintainability of systems. Installing Kubernetes does not make an application safer; setting up a CI/CD pipeline does not guarantee reliable deployments. It is the way you use these tools that makes the difference.
This summary lesson gathers the DevSecOps best practices of 2026 into four pillars: software supply chain security (SBOM, SLSA), reliability driven by SLOs and the error budget, observability with OpenTelemetry, and standardisation through Golden Paths. It is for teams that already have tools in place and want them to converge. The commands and configurations shown were run with the versions quoted.
What you will learn
- Structure your practices around the four pillars: security, reliability, operability, maintainability
- Generate and analyse an SBOM, sign an image and place your build on the SLSA scale
- Define SLIs, SLOs and an error budget to balance velocity and stability
- Instrument a service with OpenTelemetry and route its signals through a collector
- Build a Golden Path that standardises without imposing bureaucracy
- Spot the most frequent traps (security at the end of the cycle, ignored alerts, untested backups)
This lesson closes the course: it connects notions seen in earlier modules, from the DevSecOps fundamentals to reliability, without repeating them. Each section points to the lesson that goes deeper into the topic.
What are the 4 pillars of DevSecOps best practices?
DevSecOps best practices are organised around four complementary pillars, each answering a question every production system must ask. Neglecting one causes problems sooner or later: an application can be secure but impossible to diagnose, or reliable but impossible to evolve. Golden Paths apply all four by default, and the DORA metrics measure the effect.
| Pillar | Goal | Key question |
|---|---|---|
| Security | Protect data and systems | How do you detect a vulnerability before production? |
| Reliability | Guarantee availability and performance | How do you withstand an outage without user impact? |
| Operability | Monitor, diagnose, react | How do you find the cause of an incident in minutes? |
| Maintainability | Evolve and fix easily | How do you change this system in six months? |
Why formalise best practices?
Without a shared framework, each team invents its own solutions, often in a hurry. Mistakes repeat, technical debt piles up, and incidents become the norm rather than the exception. These symptoms overlap with the DevOps anti-patterns: recognising them early saves months of catch-up.
The most frequent warning signs are well known: vulnerabilities found in production, duplicated configurations and ad hoc scripts, incidents that repeat for lack of lessons learned, diverging environments, backups never restored, ignored alerts and abandoned dashboards.
Pillar 1: how do you build security in?
Security costs less when it is built in early. A vulnerability detected at commit time is fixed in minutes; the same one found in production can take days of work, not counting the impact.
Shift-left moves controls as early as possible: analyse dependencies before merge, detect secrets before commit, block vulnerable images before production. Upstream of the code, STRIDE threat modeling helps prioritise the most likely attack scenarios.
To prioritise your controls, the OWASP Top 10:2025, published in its final version in January 2026, puts broken access control first (A01), security misconfiguration at A02, then software supply chain failures at A03, which broaden the former vulnerable components category. The OWASP Top 10 for DevSecOps lesson turns these risks into CI/CD controls.
The essential practices
These practices form the minimum foundation. They are ranked by ease of implementation: the first three roll out in a few days, the next ones need more organisation and buy-in from several teams.
| Practice | Concrete action |
|---|---|
| Dependency analysis | Scan dependencies in CI (Trivy, Grype, OSV-Scanner) |
| Secrets management | Never a secret in clear text; Vault, SOPS or Sealed Secrets |
| Least privilege | Service accounts with minimal permissions, reviewed every quarter |
| Image analysis | Block images carrying fixable critical CVEs |
| SAST and DAST | Static and dynamic analysis built into the pipeline |
| Security code review | Security checklist in merge requests |
SBOM and SLSA: securing the supply chain
The software supply chain became critical after SolarWinds and Log4Shell: flawless code protects nothing if a dependency or the build is compromised. Two standards complement each other: the SBOM answers "what is my software made of?", SLSA answers "can I trust how it was built?". The supply chain security lesson details attacks and countermeasures.
The Software Bill of Materials (SBOM) is the full inventory of a piece of software's components, direct and transitive dependencies, in SPDX (Linux Foundation) or CycloneDX (OWASP) format. It is used to trace CVEs, check licences and answer "are we affected?" in minutes. With Syft 1.51 and Grype 0.118, on an image pinned by digest:
# Generate the SBOM (the "packages" subcommand is deprecated in favour of "scan")syft scan alpine:3.22@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8 \ -o spdx-json=sbom.spdx.json
# Look for known vulnerabilities in the SBOM, without re-analysing the imagegrype sbom:./sbom.spdx.jsonGrype lists each vulnerable package with its CVE, severity and EPSS score (probability of exploitation).
SLSA (Supply-chain Levels for Software Artifacts) dropped its former four-level scale in 2023 for a cumulative Build track from L0 to L3; version 1.2, approved, adds a Source track.
| Build level | Requirements | Protects against |
|---|---|---|
| L0 | No guarantee: local build, no provenance | Nothing |
| L1 | Provenance generated, even by the developer | Undocumented build errors |
| L2 | Build on a hosted service that generates and signs provenance | After-the-fact tampering with provenance |
| L3 | Isolated build, provenance unforgeable even by the build script | Compromise of the pipeline itself |
On GitHub Actions, the official generator is a reusable workflow, called at job level and not as a step. A documented exception to the SHA pinning rule: its README requires a reference by full tag @vX.Y.Z, otherwise slsa-verifier cannot verify the builder.
provenance: needs: [build] permissions: actions: read # read the calling workflow id-token: write # sign the provenance through OIDC contents: write # publish the provenance in the release uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 with: base64-subjects: "${{ needs.build.outputs.digests }}"Cosign signs an image and verifies the signature; Sigstore provides the public infrastructure (the Rekor transparency log) that makes verification possible without managing certificates yourself. You always sign an image by its digest, never by a tag, which can be moved:
cosign generate-key-paircosign sign --key cosign.key registry.example.org/app@sha256:<digest>cosign verify --key cosign.pub registry.example.org/app@sha256:<digest>Tested with Cosign 3.1.1 on a local registry: verification succeeds with the public key and fails on an unsigned image ("no signatures found"). The Sign and verify with Cosign lesson goes further, keyless signing included.
Pillar 2: how do you make a system reliable?
The question is not whether an outage will happen, but when. Reliable systems are not those that never fail, but those that withstand failures and recover quickly. Two principles underpin them: immutability (you replace a system rather than modifying it in production) and redundancy (a local failure does not reach the service).
The essential practices
These practices reduce the probability and impact of an outage. Infrastructure as code guarantees reproducibility, redundancy absorbs local failures, and chaos engineering checks that these safety nets work before a real incident does it for you.
| Practice | Concrete action |
|---|---|
| Infrastructure as Code | All infrastructure versioned (Terraform, OpenTofu, Ansible) |
| Immutability | No manual change in production: redeploy |
| Redundancy | Several availability zones for critical services |
| Circuit breakers | Isolate failures to avoid cascades |
| Chaos engineering | Regular resilience tests (Chaos Mesh, LitmusChaos) |
| Capacity | Load projections and performance tests |
The error budget: balancing velocity and stability
The error budget is an SRE concept that turns reliability into a decision. Rather than aiming for 100 % availability, impossible and costly, you set an SLO and accept the remaining gap as a budget. The SLOs, SLIs and error budgets lesson details the calculations and burn rate alerts.
-
Define the SLIs (Service Level Indicators)
What you measure, from the user's point of view: share of successful requests, share of requests served under 200 ms.
-
Set the SLOs (Service Level Objectives)
The internal target over a rolling window: for example 99.9 % successful requests over 30 days.
-
Compute the error budget
Error budget = 100 % - SLO. With a 99.9 % SLO, the budget is 0.1 %, about 43 minutes of downtime over 30 days, or 8 h 45 over a year.
-
Apply a policy
An example policy, to negotiate with product: above 50 % remaining budget, ship and experiment; between 20 and 50 %, ship while reinforcing reliability; below 20 %, suspend new features; budget exhausted, freeze and incident review.
Pillar 3: how do you make a system operable?
You cannot fix what you cannot see. Observability instruments the system to understand its behaviour in production, from three signals: metrics (what is happening?), logs (what happened?) and traces (where does a request go?). The observability lesson goes deeper into these signals.
The essential practices
These practices turn an assumption into certainty when an incident hits. Start with dashboards and alerts, then formalise runbooks and postmortems once the first incidents have been handled.
| Practice | Concrete action |
|---|---|
| Three correlated signals | Metrics, logs and traces linked by a trace identifier |
| Useful dashboards | Indicators that serve a decision, no vanity metrics |
| SLO-based alerts | Thresholds derived from SLOs, not arbitrary values |
| Runbooks | A documented procedure for each critical alert |
| Postmortems | Blameless analysis after every major incident |
| On-call | Sustainable rotation, trained and equipped teams |
On-call must stay sustainable so as not to wear teams out, and the postmortem turns an incident into collective learning rather than a search for a culprit.
OpenTelemetry: instrument once, route anywhere
OpenTelemetry (OTel) is the instrumentation standard: the CNCF graduated it on 21 May 2026, its highest maturity level. Traces, metrics and logs are stable; a fourth signal, profiling, has been in public alpha since March 2026 and is not yet meant for production. You instrument once, and the collector receives, transforms and routes the data to the backend of your choice.
On the application side, the SDK creates spans and exports them over OTLP to the collector. The service name, carried by the resource, identifies traces in the backend. Tested with the Python SDK 1.45 against a 0.161 collector: the trace arrives with its attribute.
from opentelemetry import tracefrom opentelemetry.sdk.resources import Resourcefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# The service name identifies traces in the backend.provider = TracerProvider(resource=Resource.create({"service.name": "orders"}))# http:// scheme: gRPC connection without TLS, acceptable on an internal network.provider.add_span_processor( BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4317")))trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
def process_order(order_id: str) -> None: with tracer.start_as_current_span("process_order") as span: span.set_attribute("order.id", order_id) # ... business logicThe dedicated jaeger and loki exporters are gone from the contrib distribution: Jaeger and Loki now accept OTLP natively. An old configuration naming them is rejected by otelcol-contrib validate ("unknown type: "jaeger""); this one is accepted by collector 0.161.0. The memory_limiter processor comes first to protect the collector under load.
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318
processors: memory_limiter: check_interval: 1s limit_mib: 1000 batch: timeout: 1s send_batch_size: 1024
exporters: otlp/jaeger: endpoint: jaeger:4317 tls: insecure: true prometheus: endpoint: 0.0.0.0:8889 otlphttp/loki: endpoint: http://loki:3100/otlp
service: pipelines: traces: receivers: [otlp] processors: [memory_limiter, batch] exporters: [otlp/jaeger] metrics: receivers: [otlp] processors: [memory_limiter, batch] exporters: [prometheus] logs: receivers: [otlp] processors: [memory_limiter, batch] exporters: [otlphttp/loki]Pillar 4: how do you keep a system maintainable?
A system is changed far more often than it is written. Maintainability makes these changes easier: a README that explains how to run the project, ADRs (Architecture Decision Records) that keep track of choices, tests that act as a living specification. It is the difference between a project you evolve calmly and a project you are afraid to touch.
The essential practices
These practices keep a system from becoming a black box nobody dares to change. They require continuous discipline: documentation and tests degrade quickly if nobody devotes regular time to them.
| Practice | Concrete action |
|---|---|
| Up-to-date documentation | README, ADRs (in French), diagrams, in the repository |
| Tested backups | A restore actually run every month |
| Recovery plan | Exercised at least once a year with the teams |
| Semantic versioning | Clear API contracts, documented breaking changes |
| Continuous refactoring | Time set aside to reduce debt |
| Automated tests | Enough coverage to refactor without fear |
Automated tests deserve a specific investment: without this net, a system freezes for fear of regression. The testing strategies lesson helps prioritise between unit, integration and end-to-end tests.
How do you standardise without constraining with Golden Paths?
Golden Paths are marked routes that apply the four pillars by default: a developer who follows them ships quickly while respecting the organisation's practices. They are the heart of Platform Engineering, which builds a self-service internal platform.
According to the DORA 2025 report, 90 % of organisations already use an internal platform and 76 % have a dedicated platform team. A Golden Path remains a recommendation, not an obligation: teams can deviate for a good reason, but the default path must be the easiest to follow. It is built from four building blocks, from the cheapest to the most demanding.
-
A project template
Repository structure, Dockerfile, CI/CD pipeline and base configuration ready to use. In Backstage, it is a Software Template that the developer instantiates from the portal; it creates for example
src/,Dockerfile,.gitlab-ci.yml, the Kubernetes manifests, adocs/adr/folder and the README. -
A self-service portal
An interface to create resources without a ticket: Backstage in open source, Port or Humanitec as managed products.
-
Built-in documentation
Guides live in the workflow and in the repository, not on a separate wiki: this is the Docs-as-Code approach (in French).
-
Automatic guardrails
Admission policies that prevent mistakes at deployment time, like this Kyverno
ValidatingPolicythat requires ateamlabel.
The policy below was tested with the Kyverno CLI 1.19.1: a Deployment carrying the team label is admitted, a Deployment without it is rejected with the expected message.
apiVersion: policies.kyverno.io/v1kind: ValidatingPolicymetadata: name: require-labelsspec: validationActions: [Deny] matchConstraints: resourceRules: - apiGroups: ["apps"] apiVersions: ["v1"] operations: ["CREATE", "UPDATE"] resources: ["deployments"] validations: - expression: >- has(object.metadata.labels) && 'team' in object.metadata.labels && size(object.metadata.labels['team']) > 0 message: "The 'team' label is mandatory on every Deployment."Two concrete scenarios
These two scenarios compare, on frequent cases, what happens with and without the practices described. They show the gap between a team that has formalised its reflexes and a team that discovers the problem as it happens.
Scenario 1: an API key committed by mistake
A developer commits an API key to the source code by mistake. Without best practices, the key stays in Git history and an audit finds it six months later: rotation of all access, forensic analysis, crisis communication. With them, the pre-commit hook (Gitleaks, detect-secrets) blocks the commit; if it gets through anyway, the CI scan fails, the key is revoked and replaced from the secrets manager, and the incident is documented.
Scenario 2: an incident on a Friday evening
The application returns 500 errors and the on-call engineer is paged. Without best practices, they spend hours in unstructured logs, with no runbook, before a risky manual rollback. With them, the alert points to the runbook, the dashboard shows the correlation with the 5 pm deployment, the rollback is triggered in one action and the service is back in minutes; the postmortem is scheduled for Monday.
Which traps should you avoid?
This table sums up the most frequent mistakes, often inherited from a culture where velocity trumps everything. Spotting them early saves months of catch-up; the right-hand column gives the fix for each.
| Trap | Why it is a problem | Fix |
|---|---|---|
| Security at the end of the cycle | Costly fixes, delivery delays | Analyse from the commit |
| Too many alerts | Alert fatigue, ignored alerts | SLO-derived thresholds, noise removal |
| Untested backups | Restore impossible on D-day | A real monthly restore |
| Outdated documentation | Lost trust, procedure errors | Docs in the repository, reviewed in each merge request |
| Manual environments | Divergence, "works on my machine" | Everything as IaC, ephemeral environments |
| Least privilege ignored | Wider attack surface | Quarterly permission review |
| Punitive postmortems | Errors get hidden | Blameless culture, focus on the system |
| Accumulated technical debt | Velocity in free fall | Time set aside in each iteration |
How do you know your practices are mature?
Go through this checklist every quarter rather than once. It relies in particular on the DORA metrics, five since 2024: change lead time, deployment frequency, failed deployment recovery time, change fail rate and rework rate. Tracking security KPIs completes the measurement.
- No secret in clear text in repositories or pipelines
- Images are analysed and vulnerability management blocks critical flaws before deployment
- An SBOM is generated automatically for every release
- All infrastructure is versioned and reproducible
- SLOs are defined and the error budget is tracked
- Every critical alert links to a runbook
- Backup restores are tested at least every quarter
- A blameless postmortem follows every major incident
- Teams deploy autonomously, without manual intervention
- The five DORA metrics are measured and tracked over time
Key points
- Security is built in from the first commit: SBOM, signing by digest and a build assessed on the SLSA scale (L0 to L3).
- The OWASP Top 10:2025 ranks software supply chain failures third among application risks.
- Reliability is driven by SLOs and an error budget, not by a promise of 100 % availability.
- Operability relies on OpenTelemetry, CNCF graduated in May 2026, and on actionable runbooks (in French).
- Maintainability requires documentation in the repository, tests and backups actually restored.
- Golden Paths apply these practices by default, without imposing them.
- An example that worked two years ago may no longer work: retired OpenTelemetry exporters, deprecated subcommands, SHA pinning incompatible with the SLSA generator. Replay your examples with current versions.
Knowledge check
Check that you have the essentials of this guide. The questions only cover what has just been explained here.
Knowledge check
Check what you have learned with this interactive quiz
How it works
- The timer starts when you click Start
- Multiple choice, true/false and short answer questions
- You can move between questions
- Detailed results are shown at the end
Starts the quiz and the timer
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: DevSecOps common thread: notes-api from V0 to V11
A new full quiz with random questions
Work again only on the questions you missed
FAQ: frequently asked questions
The questions below cover the most frequent doubts about DevSecOps best practices: SBOM and SLSA, the error budget, Golden Paths and OpenTelemetry.