Overview

When I took over an operations team in 2021, I ran a simple audit: 12 people, 40 hours per week each, averaging 24 hours spent on manual ticket handling, service restarts, and disk space cleanup. That’s 60% toil. Of the remaining 16 hours, half went to status meetings. Actual engineering time: under 8 hours per week per person.

Everyone was busy, but the system was still unstable. MTTR sat at 40 minutes, availability at 99.5%, and the alert channel saw 200+ messages daily. My boss asked: “Is our team any good?” I couldn’t answer. Not out of modesty — I had no quantitative standard to measure against.

Over the next three years, I pushed availability from 99.5% to 99.9%, cut MTTR from 40 minutes to 8, and reduced toil from 60% to under 20%. Looking back, the pivotal step wasn’t adopting a specific tool — it was building a maturity assessment framework. First, figure out where the team stands. Then decide what to invest in next.

This article shares the SRE team maturity model I’ve used in practice. It borrows the layered approach from CMMI but is designed entirely for SRE scenarios, with quantifiable criteria at every level. At the end, there’s a Python self-assessment script — run it and you’ll know which level your team is at.

Why You Need an SRE Maturity Model

Let me list a few common scenarios. See how many you recognize:

  • When hiring, the JD says “proficient in K8s and Prometheus.” You interview a batch of candidates with similar stacks, but their actual output varies wildly — because you don’t know whether the team needs “someone who can write PromQL” or “someone who can design an SLO system”
  • When requesting budget, you tell the boss “we need Datadog and a chaos engineering platform.” The boss asks “What level are we at now? What level will we reach after investing?” You can’t answer
  • In cross-team collaboration, developers think SRE only blocks releases, while SRE thinks developers don’t care about stability — the root cause is no shared understanding of “what should SRE do”
  • Someone on the team wants to push automation; someone else thinks “manual works fine, why change?” As the lead, you can’t persuade them with data

The common root cause: no quantifiable ruler to measure team capability.

CMMI addresses software process improvement — requirements management, configuration management, quality assurance. An SRE maturity model doesn’t care about “how you write code” but “how you keep production systems running reliably” — which services are monitored, how fast you recover from incidents, whether changes can auto-rollback, how much time the team spends on engineering vs. toil.

Traditional ops is “something broke, I’ll fix it,” while SRE is “use engineering methods to prevent problems and recover fast when they do occur” — the two positions are fundamentally different.

The 5-Level SRE Team Maturity Model

I referenced CMMI’s five-level structure (Initial → Managed → Defined → Quantitatively Managed → Optimizing), combined it with the core practices from the Google SRE Book and my own deployment experience across multiple projects, to design this SRE-specific maturity model.

L1: Reactive (Firefighting)

Core characteristics: Passive response, manual operations, no system.

Key metrics range:

MetricTypical ValueNotes
MTTR30-60 minHuman investigation, no standard process
Toil ratio50%-70%Heavy repetitive manual work
Alert accuracy<30%Massive false positives, alert fatigue
SLO coverage0%No SLOs defined
Change rollbackManualHuman rollback, wrong versions common

Common signs:

  • Monitoring dashboards are the default templates from Prometheus installation, untouched
  • Alerts configured as “CPU > 80% → alert,” firing day and night into group chat
  • Incidents start with “who touched what?” in chat logs
  • Ops knowledge lives in a senior engineer’s head; when they’re on vacation, things break
  • Deployments via manual kubectl apply; rollback via manual kubectl rollout undo

My first team was in this state. Not that the team was incompetent — everyone had solid skills, but the team had no engineering mindset. Every problem was solved by “watching more closely.”

L2: Managed

Core characteristics: Has processes, has role division, has basic monitoring, but driven by rules rather than data.

Key metrics range:

MetricTypical ValueNotes
MTTR15-30 minOn-call rotation and troubleshooting docs exist
Toil ratio40%-50%Some scripted operations, but high maintenance cost
Alert accuracy30%-50%Severity levels exist, but strategy is coarse
SLO coverage<20%SLOs may be defined for core services but not operationalized
Change rollbackSemi-autoCI/CD has a rollback button, but human judgment required

Common signs:

  • On-call rotation schedule exists; midnight alerts are answered, but shift handover relies on word of mouth
  • Runbooks exist, but documentation lags behind actual operations — “the doc says step A, but you actually need to do B”
  • Prometheus + Grafana deployed, but dashboards are copied templates, never tuned for the actual business
  • CI/CD pipeline runs, but release frequency is limited by “releases need Manager Wang’s approval”
  • Postmortems happen, but conclusions are “improve monitoring” or “raise awareness” — nothing actionable

On-Call rotation design is a big topic. Related: The 3 AM Phone Rings Again: 7 Engineering Decisions for On-Call Rotation Design and Fatigue Management covers it in detail.

The transition from L1 to L2 is relatively easy — the core action is establishing processes and role division. But many teams get stuck at L2 because the jump to L3 isn’t about “adding more processes.” It requires a mindset shift — from “rules-driven” to “data-driven.”

L3: Measured

Core characteristics: SLI/SLO system operationalized, error budgets drive decisions, alerts based on SLOs rather than thresholds.

Key metrics range:

MetricTypical ValueNotes
MTTR8-15 minPrecise alerts, standardized troubleshooting paths
Toil ratio25%-40%Automation covers core ops
Alert accuracy60%-80%SLO burn rate alerts replace threshold alerts
SLO coverage60%-80%Core and important services have SLOs
Change rollbackAuto-triggeredBased on error budget or health checks

Common signs:

  • Every core service has defined SLIs (availability, latency, error rate); SLO targets agreed with product owners
  • Alerts are no longer “CPU 80%” but “error budget burn rate abnormal,” reducing invalid alerts by 70%+
  • Postmortems use structured templates; every action item has an owner and deadline
  • Infrastructure managed via IaC (Terraform/Ansible); no manual resource creation
  • Capacity planning awareness exists; pre-sale load testing and scaling plans are standard

When I deployed an SLO system in a ride-hailing project, the most tangible change was: the alert channel went from 200+ messages/day to under 20, and every one required immediate action. The team went from “chased by alerts” to “look at alerts when there’s a problem.” MTTR dropped from 30 minutes to 8 — not because investigation got faster, but because alerts became accurate, reducing localization time from 25 minutes to 3.

For the specifics of SLI/SLO system design, Related: SRE Core Concepts: SLI, SLO and Error Budgets has a complete walkthrough.

L4: Engineering

Core characteristics: Platform-based operations, automation across the full chain, reliability gates embedded in the development process.

Key metrics range:

MetricTypical ValueNotes
MTTR3-8 minAutomated diagnosis + self-healing
Toil ratio15%-25%Ops platformized, self-service
Alert accuracy80%-95%Alerts as tickets, with context
SLO coverage80%-95%Including non-core services
Change rollbackSystematicMulti-layer defense (canary → health check → auto-rollback → error budget gate)

Common signs:

  • Ops platformization: 20+ operations (scaling, restarts, config changes, log cleanup) integrated into a self-service platform; developers can self-serve
  • New services must pass a Production Readiness Review (PRR) before launch
  • Change management driven by error budgets: ample budget means free releases; tight budget automatically tightens approval
  • Monitoring as Code: alert rules managed via Terraform or YAML, version-controlled and reviewable
  • Capacity planning backed by data models, not gut feeling — based on historical trends and load test data

The biggest shift at this stage is that SRE moves from “operator of services” to “engineer of reliability.” The team doesn’t directly operate a specific service — it builds platforms and tools that let development teams self-serve their operations.

For the specifics of ops platformization architecture, see Related: From “@ Ops in Chat” to Self-Service: 6-Layer Architecture and 4 Landing Phases for Platformizing 20+ Operations.

L5: Optimizing

Core characteristics: Continuous experimentation and improvement, chaos engineering as routine, AI-assisted decision-making.

Key metrics range:

MetricTypical ValueNotes
MTTR<3 minMost incidents self-heal, no human intervention
Toil ratio<15%Team spends 85%+ on engineering
Alert accuracy>95%Predictive alerts, early warning before incidents
SLO coverage>95%Full coverage, including third-party dependencies
Change rollbackPreventivePre-change auto-validation; non-compliant changes blocked at source

Common signs:

  • Chaos engineering executed regularly; faults actively injected to validate system resilience
  • Alerts shift from “reactive” to “predictive”: trend analysis warns before incidents occur
  • Capacity elasticity fully automated: HPA/VPA/CA working together; scaling from 25 minutes to 1 minute
  • Knowledge management evolves from “documents” to “executable Runbooks”: the platform recommends handling plans based on incident type
  • Team time allocation: 85% engineering (platform development, SLO optimization, chaos experiments), 15% daily operations

Frankly, L5 is an ideal state. Google itself is still working toward it. Among Chinese teams I’ve seen, those at L4 are already top-tier. But L5 provides a direction — knowing where the destination is makes every step in between meaningful.

6 Assessment Dimensions

Having a 5-level model isn’t enough — you need to know which dimensions to assess. Below are the 6 assessment dimensions I’ve used in practice, each with specific quantifiable metrics.

Dimension 1: Incident Response Capability

Evaluates your team’s response speed and standardization when incidents occur.

Assessment ItemL1L2L3L4L5
MTTR30-60min15-30min8-15min3-8min<3min
Severity gradingNoneExperience-basedSEV levels definedAuto-classifiedPredictive
Postmortem executionNoneDone but untrackedStructured + action trackingAction completion >80%Auto-tracked
On-CallNoneRotation but fatiguedRotation + fatigue controlRotation + automation assistSelf-healing primary

Dimension 2: SLO Adoption

The SLI/SLO system is the foundation of SRE. Without SLOs, talking about reliability is just guessing.

Assessment ItemL1L2L3L4L5
SLO coverage0%<20%60-80%80-95%>95%
Error budgetNoneConcept understoodOperationalized + alertsDrives release decisionsDrives product decisions
SLI definitionNoneManual configStandardized templateIaC managedAuto-discovered
SLO reviewNoneNoneQuarterlyMonthly adjustmentContinuous optimization

Dimension 3: Toil Ratio

The Google SRE Book caps operational toil at 50%. This is a hard constraint — above 50%, the team has no time for engineering improvements,陷入 a vicious cycle of “the busier you are, the less time for improvement, the busier you get.”

Assessment ItemL1L2L3L4L5
Toil ratio50-70%40-50%25-40%15-25%<15%
Automation coverage<10%10-30%30-60%60-85%>85%
Repeat task identificationNot identifiedOccasionally foundRegular auditsPlatform-eliminatedPredictively eliminated
Ticket volumeUntrackedTracked but unanalyzedTrend analysisCategorized treatmentAuto-routed

Dimension 4: Change Safety

Change-induced incidents account for over 60% of all incidents (Google SRE Book data). Change management is a core dimension of SRE maturity.

Assessment ItemL1L2L3L4L5
Rollback methodManualHas buttonSemi-autoAuto + multi-layerPreventive
Canary strategyNoneManual canaryAuto canaryCanary + traffic managementAuto + A/B testing
Change reviewNoneManual approvalPR ReviewAutomated gatesPredictive gates
Change freezeNoneManual for big eventsError budget drivenDynamic windowsRisk-predictive freeze

Dimension 5: Observability Coverage

Observability isn’t just “installed Prometheus” — the key is whether you can answer “is the system healthy right now?” without looking at logs.

Assessment ItemL1L2L3L4L5
Monitoring coverageCore servicesCore fullCore full + importantFull + dependenciesFull + third-party
Alert strategyThresholdTiered thresholdsSLO burn rateAlert-as-ticketPredictive alerts
Log coverageKey logsStructured logsCentralized + searchableLogs-as-dataAuto root cause
TracingNonePartialCore tracesFull chainAuto topology

Dimension 6: Knowledge Management

Knowledge management is the most easily overlooked dimension. Many teams aren’t technically weak, but knowledge transfer is so inefficient that new hires take 3 months to ramp up, and when senior people leave, knowledge gaps appear.

Assessment ItemL1L2L3L4L5
RunbookNoneOutdatedRegularly updatedExecutableAuto-recommended
Architecture diagramWord of mouthExists but inaccurateVersionedIaC-generatedReal-time topology
Case libraryNoneExists but unusedSearchableStructured + linkedAuto-matched
Training mechanismMentorshipOccasionalRegular sharingSystematic curriculumAutomated learning

Quantitative Self-Assessment Script

Looking at tables isn’t intuitive enough. Below is a Python script — input your team’s actual situation for each dimension, and it’ll calculate your maturity score and level.

#!/usr/bin/env python3
"""SRE Team Maturity Self-Assessment Scoring Script

Usage: python3 sre_maturity_score.py
Enter data for each dimension as prompted; outputs maturity level and recommendations.
"""

import json
import sys

# 6 assessment dimensions and scoring rules
# Each dimension scores 100; 6 dimensions total 600
# L1: <150, L2: 150-250, L3: 250-380, L4: 380-480, L5: >480

DIMENSIONS = {
    "incident_response": {
        "name": "Incident Response Capability",
        "questions": [
            {
                "key": "mttr",
                "prompt": "Team average MTTR (minutes)",
                "scores": {60: 10, 30: 25, 15: 45, 8: 70, 3: 90, 0: 100},
            },
            {
                "key": "severity",
                "prompt": "Severity grading (1=None 2=Experience 3=SEV defined 4=Auto 5=Predictive)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
            {
                "key": "postmortem",
                "prompt": "Postmortem action item completion rate (0-100%)",
                "scores": lambda x: min(100, int(x)),
            },
            {
                "key": "oncall",
                "prompt": "On-Call mechanism (1=None 2=Rotation 3=Rotation+fatigue control 4=+automation 5=Self-healing)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
        ],
    },
    "slo_adoption": {
        "name": "SLO Adoption",
        "questions": [
            {
                "key": "slo_coverage",
                "prompt": "SLO coverage rate (0-100%)",
                "scores": lambda x: min(100, int(x)),
            },
            {
                "key": "error_budget",
                "prompt": "Error budget usage (1=None 2=Concept 3=Operationalized 4=Drives releases 5=Drives product)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
            {
                "key": "sli_standard",
                "prompt": "SLI definition (1=None 2=Manual 3=Standardized 4=IaC 5=Auto-discovered)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
        ],
    },
    "toil_ratio": {
        "name": "Toil Ratio",
        "questions": [
            {
                "key": "toil_pct",
                "prompt": "Ops toil ratio (0-100%)",
                "scores": lambda x: max(0, 100 - int(x) * 1.5),
            },
            {
                "key": "automation",
                "prompt": "Automation coverage (0-100%)",
                "scores": lambda x: min(100, int(x)),
            },
        ],
    },
    "change_safety": {
        "name": "Change Safety",
        "questions": [
            {
                "key": "rollback",
                "prompt": "Rollback method (1=Manual 2=Button 3=Semi-auto 4=Auto+multi-layer 5=Preventive)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
            {
                "key": "canary",
                "prompt": "Canary strategy (1=None 2=Manual 3=Auto 4=Canary+traffic mgmt 5=Auto+A/B)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
            {
                "key": "change_gate",
                "prompt": "Change review (1=None 2=Manual approval 3=PR Review 4=Automated 5=Predictive)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
        ],
    },
    "observability": {
        "name": "Observability Coverage",
        "questions": [
            {
                "key": "monitoring",
                "prompt": "Monitoring coverage (0-100%)",
                "scores": lambda x: min(100, int(x)),
            },
            {
                "key": "alerting",
                "prompt": "Alert strategy (1=Threshold 2=Tiered 3=SLO burn 4=Alert-as-ticket 5=Predictive)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
            {
                "key": "tracing",
                "prompt": "Tracing (1=None 2=Partial 3=Core 4=Full chain 5=Auto topology)",
                "scores": {1: 10, 2: 30, 3: 55, 4: 80, 5: 100},
            },
        ],
    },
    "knowledge": {
        "name": "Knowledge Management",
        "questions": [
            {
                "key": "runbook",
                "prompt": "Runbook status (1=None 2=Outdated 3=Updated regularly 4=Executable 5=Auto-recommended)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
            {
                "key": "architecture",
                "prompt": "Architecture diagram (1=Word of mouth 2=Inaccurate 3=Versioned 4=IaC-generated 5=Real-time)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
            {
                "key": "case_library",
                "prompt": "Case library (1=None 2=Unused 3=Searchable 4=Structured 5=Auto-matched)",
                "scores": {1: 10, 2: 25, 3: 50, 4: 75, 5: 100},
            },
        ],
    },
}

LEVEL_NAMES = {
    1: "L1 Reactive (Firefighting)",
    2: "L2 Managed",
    3: "L3 Measured",
    4: "L4 Engineering",
    5: "L5 Optimizing",
}

LEVEL_THRESHOLDS = [
    (0, 150, 1),
    (150, 250, 2),
    (250, 380, 3),
    (380, 480, 4),
    (480, 601, 5),
]


def score_question(q, answer):
    """Calculate score for a single question based on the answer."""
    scores = q["scores"]
    if callable(scores):
        return scores(answer)
    # Find the largest key <= answer
    best = 0
    for threshold, score in sorted(scores.items()):
        if answer >= threshold:
            best = score
    return best


def run_assessment():
    """Interactive self-assessment."""
    print("=" * 60)
    print("SRE Team Maturity Self-Assessment")
    print("=" * 60)

    results = {}
    total = 0

    for dim_key, dim in DIMENSIONS.items():
        print(f"\n--- {dim['name']} ---")
        dim_score = 0
        q_count = len(dim["questions"])
        for q in dim["questions"]:
            while True:
                try:
                    raw = input(f"  {q['prompt']}: ").strip()
                    if q["scores"] == q.get("scores") and callable(q["scores"]):
                        answer = float(raw)
                    elif isinstance(q["scores"], dict):
                        answer = int(raw)
                        if answer not in q["scores"] and max(q["scores"].keys()) > 5:
                            answer = float(raw)
                    else:
                        answer = float(raw)
                    break
                except ValueError:
                    print("    Invalid input, please try again")
            s = score_question(q, answer)
            dim_score += s
            results[f"{dim_key}.{q['key']}"] = {"answer": raw, "score": s}

        dim_avg = round(dim_score / q_count)
        print(f"  -> {dim['name']} Score: {dim_avg}/100")
        total += dim_avg

    # Determine level
    level = 1
    for low, high, lv in LEVEL_THRESHOLDS:
        if low <= total < high:
            level = lv
            break

    print("\n" + "=" * 60)
    print(f"Total Score: {total}/600")
    print(f"Maturity Level: {LEVEL_NAMES[level]}")
    print("=" * 60)

    # Improvement recommendation
    weakest = min(
        DIMENSIONS.keys(),
        key=lambda k: sum(
            results[f"{k}.{q['key']}"]["score"]
            for q in DIMENSIONS[k]["questions"]
        ) / len(DIMENSIONS[k]["questions"]),
    )
    print(f"\nWeakest dimension: {DIMENSIONS[weakest]['name']}")
    print(f"Recommended priority: Invest in {DIMENSIONS[weakest]['name']} improvements")
    print(f"Full results saved to sre_maturity_result.json")

    with open("sre_maturity_result.json", "w") as f:
        json.dump({"total": total, "level": level, "details": results}, f, indent=2)

    return total, level


if __name__ == "__main__":
    run_assessment()

I’ve used this script within my team for two years. Running it every quarterly review and comparing scores against the previous quarter shows whether the last three months actually moved the needle. Far more convincing than telling the boss “we’ve done a lot of optimization.”

6 Transition Decisions

Moving from one level to the next doesn’t happen naturally — it requires deliberate investment. Below are 6 key decisions, each one I’ve made in real projects.

Decision 1: L1→L2, On-Call First or Monitoring First?

My recommendation: On-Call first.

The reasoning is direct: monitoring can be copied from templates, but On-Call establishes the fundamental collaboration relationship of “who’s responsible, who to find when things break.” Without this relationship, nobody watches even the best monitoring.

Specific actions:

  • Define an On-Call rotation, 7-day cycles, primary and secondary each
  • Define alert channels: P0 phone, P1 SMS + group message, P2 group message
  • Build a shift handover checklist: unresolved alerts, upcoming changes, known risks
  • During On-Call, toil should not exceed 25% of time (Google standard); above that means the rotation is poorly designed

Pitfall: My first rotation put the strongest engineer on primary every time. He became “the endpoint for every problem” — not only was he exhausted, the rest of the team never learned. The correct approach is pairing strong with weak: primary handles P0, secondary handles P1 and learns from primary.

Decision 2: L2→L3, SLO First or Alert Cleanup First?

My recommendation: SLO first, let SLOs drive alert cleanup.

Cleaning alerts first is a trap — without a standard, how do you decide which alert to delete? Delete the wrong one and who takes the blame? SLO gives you an objective standard: any fluctuation that doesn’t consume error budget shouldn’t trigger an alert.

Deployment sequence:

  1. Pick 1-2 core services, define SLIs (start with availability: successful requests / total requests)
  2. Confirm SLO targets with product owners (don’t decide alone; get business buy-in)
  3. Configure error budget burn rate alerts, replacing old CPU/memory threshold alerts
  4. Observe for 2 weeks; after confirming new alert effectiveness, gradually clean old alerts

Measured data: After deploying SLOs in a ride-hailing project, alert volume dropped from 200/day to 20/day, alert accuracy improved from 28% to 78%. The team saved 15 hours/week on invalid alert handling.

Decision 3: L3→L4, Where to Place Error Budget Gates

My recommendation: Three-tier gates, don’t go all-in at once.

Error budget gates are the signature practice of L4, but pushing them to all services at once triggers strong pushback from development teams. My approach: three tiers.

TierTrigger ConditionActionRollout Timing
YellowError budget consumption >50%Auto-notify dev team, suggest controlling release frequencyMonth 1
RedError budget consumption >75%New releases need SRE review, auto-canary scope narrowedMonth 2
BlackError budget depletedRelease freeze; only bugfixes and rollbacks allowedMonth 3

Pitfall: Initially, I set the red gate to “all releases require SRE approval,” turning SRE into a bottleneck — 20 release requests queued daily for approval. Later I changed it to “at red, only review high-risk releases,” dropping approval volume to 3-5/day. The gate’s purpose is reducing risk, not blocking business.

Decision 4: L4→L5, ROI of Self-Healing Platforms

My view: 80% of teams should not aim for L5.

The core feature of L5 is self-healing — most incidents resolve without human intervention. But self-healing platform development costs are extremely high: you need to design automated recovery logic for each fault type. The more fault types covered, the larger the development effort.

I saw a team spend 6 months building a self-healing platform covering 12 common fault types. After launch, they discovered: those 12 types accounted for only 35% of total incidents. The other 65% were long-tail, each occurring once or twice a year — automating them was a terrible ROI.

Pragmatic advice:

  • First, solidify L4 — 80% of incidents can be resolved through standardized ops platformization
  • Self-healing only for high-frequency faults (Top 5 fault types, accounting for 60%+ of total)
  • Everything else relies on automated assistance (auto-diagnosis + recommended plans), not full self-healing

Decision 5: Investment Priority Ranking

If you have a budget, what should you invest in? Here’s my priority table:

Maturity RangeFirst PrioritySecond PriorityNot Recommended
L1On-Call mechanism + basic monitoringRunbookChaos engineering
L2SLO system + alert cleanupCI/CD automationAIOps
L3Error budget gates + ops platformIaCSelf-healing platform
L4Self-healing (high-freq) + chaos engineeringPredictive alertsFull self-healing

Core principle: Don’t skip levels when investing. An L1 team deploying chaos engineering is a disaster — you haven’t even established a steady state, and injecting faults will only create more chaos.

Decision 6: Avoid Over-Engineering

This is the point I want to emphasize most. The maturity model is for self-assessment, not for KPIs.

I saw a team lead take this model and set “every dimension up one level in 6 months” targets. To reach L3, the team set SLOs of 99.99% for all services — but half those services weren’t that important. SLOs set too high caused development teams to be strangled by error budgets, afraid to release anything.

Correct usage:

  • Run the self-assessment quarterly; track score trends
  • Invest in the weakest dimension first; don’t pursue balanced improvement across all dimensions
  • Different services can have different targets — core services at L4, edge services at L2 is fine
  • Maturity improvement is a result, not a goal — the goal is improving system reliability and team efficiency

Production Practice: 3 Years from L1 to L4

Finally, sharing my actual transition path as a concrete timeline reference.

Year 1: L1→L2 (Establishing Order)

First 3 months:

  • Established On-Call rotation, 7-day cycles, primary + secondary pairing
  • Cleaned up alert channels: P0 phone, P1 SMS, P2 group message
  • Wrote 8 core service Runbooks — rough, but they existed

Months 3-6:

  • Prometheus + Grafana basic dashboards deployed
  • CI/CD pipeline integrated with automated testing; deployments shifted from manual apply to pipeline-triggered
  • Started tracking ticket data; first quantitative toil measurement: 55%

Months 6-12:

  • MTTR dropped from 40 to 28 minutes (mainly due to Runbooks shortening localization time)
  • Toil ratio dropped from 60% to 45%
  • Team began developing “this is an engineering problem, not an ops problem” awareness

Year 2: L2→L3 (Data-Driven)

First 6 months:

  • Defined SLI/SLOs for 3 core services; SLO coverage from 0% to 45%
  • Alert strategy switched from thresholds to SLO burn rate; alert volume dropped 70%
  • Started using Terraform for infrastructure management; manual resource creation dropped to 0

Months 6-12:

  • SLO coverage pushed to 72%
  • MTTR dropped to 12 minutes
  • Toil ratio dropped to 30%
  • Error budgets started driving release cadence; dev team moved from resistance to acceptance

Year 3: L3→L4 (Engineering)

  • Ops platform launched; 20+ operations self-service-ized; toil ratio dropped to 22%
  • Production Readiness Review implemented; new services must pass 7-dimension gate before launch
  • Change rollback evolved from “has button” to “multi-layer automated defense”
  • MTTR dropped to 8 minutes
  • Availability improved from 99.5% to 99.9%

Over three years, the team went from 12 to 8 people (headcount down 40%), but the system became far more stable. The 4 freed-up headcount weren’t laid off — they shifted to platform development and SLO optimization. That’s the value of SRE: using engineering methods to replace headcount stacking.

Alternatives and Trade-offs

DORA Metrics vs. SRE Maturity Model

DORA (DevOps Research and Assessment) defines 4 key metrics: deployment frequency, lead time for changes, change failure rate, and time to restore. Its strength is cross-industry comparability with deep data accumulation.

ComparisonDORA MetricsSRE Maturity Model
FocusDelivery efficiency + stabilityStability engineering capability
Metric count46 dimensions, 20+ items
Best forOverall R&D efficiency assessmentSRE team-specific assessment
Data acquisitionExtract from CI/CD systemsRequires multi-system synthesis
QuantificationHigh (4 precise numbers)Medium (multi-dimensional scoring)

My recommendation: DORA and SRE maturity aren’t contradictory — use both. DORA for overall R&D efficiency, SRE maturity for SRE team-specific capability. If you can only pick one, SRE teams get more value from the SRE maturity model.

CMMI vs. SRE Maturity Model

CMMI focuses on software process improvement, with 5 levels (Initial → Managed → Defined → Quantitatively Managed → Optimizing). The SRE maturity model borrows the layered approach but assesses entirely different dimensions.

CMMI asks “is your code-writing process standardized?” SRE maturity asks “can you keep production systems running reliably?” If your team does both development and operations, CMMI and SRE maturity complement each other — the former for dev processes, the latter for ops capability.

Don’t Assess for Assessment’s Sake

One final common pitfall: turning maturity assessment into a KPI evaluation tool.

The maturity model’s value is self-checking and positioning — helping you find gaps and decide where to invest next. Once it becomes a KPI, the team will game the metrics: SLO coverage at 100% but half are meaningless “99% availability” targets; 50 Runbooks written but none maintained. Scores go up, actual capability doesn’t change.

My approach: assessment results are only for internal review and planning, not tied to performance reviews. The team knows it’s a tool to help them find problems, not a whip to evaluate them. That’s the only way people will score honestly, and the assessment becomes meaningful.

Summary

Back to the opening question: is your SRE team any good?

Don’t answer by feel. Run the 5-level maturity model and 6-dimension quantitative self-assessment — the numbers will tell you.

Key takeaways:

  1. Maturity progresses in layers; you can’t skip levels. An L1 team deploying chaos engineering is a disaster. An L3 team still doing manual rollbacks is a waste. First figure out your level, then decide what to invest in.

  2. Toil ratio is the hardest metric. If 50%+ of the team’s time is manual operations, regardless of how many tools you’ve installed or docs you’ve written, you’re at L1-L2. Google SRE Book’s 50% cap isn’t a suggestion — it’s a hard constraint.

  3. SLOs are the dividing line. Without SLOs, a team is at most L2. After SLOs are operationalized, alerts, changes, and capacity planning all gain a unified standard, and the team shifts from “rules-driven” to “data-driven.”

  4. L4 is already top-tier. Few Chinese teams reach L4. L5 is ideal; 80% of teams don’t need to chase L5 — solidify L4, and 80% of incidents can be resolved through platformization.

  5. The maturity model is a self-check tool, not a KPI. Use it to find gaps and guide investment direction, not to evaluate the team. Once tied to performance, the assessment loses its value.

After deploying this model across multiple enterprise clients, the most common feedback I hear: “We used to not know what the team was missing — now we know.” That’s more valuable than any tool or process — knowing where you are is the first step to knowing where to go.

References & Acknowledgments

The following resources were referenced during the writing of this article. Thanks to the original authors for their contributions:

  1. Site Reliability Engineering — Google SRE Team, the foundational work on SRE. Core concepts in this article including the toil ratio cap, error budgets, and SLI/SLO are derived from this book.
  2. SRE Best Practices: The 2026 Playbook — Nova AI Ops, a 2026 SRE best practices overview, providing references for automated SLO monitoring and burn rate alerting practices.
  3. Setting SLOs and Error Budgets That Reduce Burnout — SquareOps, practical experience on SLO implementation and team fatigue management, referenced in the On-Call fatigue section.
  4. SRE Practice: From Concepts and Metrics to Organizational Collaboration — Alibaba Cloud Developer Community, provided a holistic perspective on SRE system building and the MTBF/MTTR measurement framework.
  5. Capability Maturity Model Integration (CMMI) — R. Morales-Fernández et al., the academic foundation of the CMMI maturity model, which inspired the 5-level layered architecture in this article.