SLA Management

SLA Credits: How Service Credits Work and Best Practices for Providers

Understand SLA credit structures, how to calculate and apply them correctly, automate credit processing, and use credits as a trust-building rather than adversarial mechanism.

AzMonitor TeamJune 11, 20257 min read · 1,447 wordsUpdated January 20, 2026
SLA creditsservice creditsSLA breachcustomer compensation

SLA credits are the financial mechanism for compensating customers when service level commitments aren't met. Their design — how they're triggered, calculated, applied, and communicated — determines whether they function as a trust-building mechanism or a source of customer frustration. Getting them right matters for both customer relationships and business sustainability.

How SLA Credits Work

At their core, SLA credits follow a simple structure:

  1. A service level commitment is defined (e.g., 99.9% monthly availability)
  2. Actual performance is measured against the commitment
  3. If performance falls below the commitment, a credit is calculated based on the credit schedule
  4. The credit is applied to the customer's next invoice or paid out directly

The complexity comes from the definitions — what counts as downtime, how credits are calculated, who initiates the claim, and how disputes are resolved.

Credit Schedule Design

Credit schedules should be progressive — more severe breaches result in larger credits:

## Example Credit Schedule Structure

### Tier 1: Minor Breach
- Threshold: 99.0% - 99.9% (below SLA target of 99.9%)
- Credit: 10% of monthly service fees
- Practical meaning: 43 minutes to 7 hours of downtime per month

### Tier 2: Significant Breach
- Threshold: 95.0% - 99.0%
- Credit: 25% of monthly service fees
- Practical meaning: 7 hours to 36 hours of downtime per month

### Tier 3: Severe Breach
- Threshold: Below 95.0%
- Credit: 50% of monthly service fees
- Practical meaning: More than 36 hours of downtime per month

### Maximums
- Maximum credit in any calendar month: 50% of monthly fee
- Credits do not accumulate across months
- Credits are the sole remedy for availability failures
  (unless contract specifies additional remedies)

Calculating Credits Correctly

from dataclasses import dataclass
from typing import Optional

@dataclass
class CreditTier:
    min_availability_pct: float
    max_availability_pct: float  # Exclusive upper bound (= SLA target)
    credit_pct: float

@dataclass
class SLAContract:
    customer_id: str
    customer_name: str
    sla_target_pct: float  # e.g., 99.9
    monthly_fee: float
    credit_schedule: list  # List of CreditTier

class SLACreditCalculator:
    
    def calculate_monthly_credit(
        self,
        contract: SLAContract,
        actual_availability_pct: float
    ) -> dict:
        """
        Calculate SLA credit for a given month's actual availability.
        """
        # No credit if SLA was met
        if actual_availability_pct >= contract.sla_target_pct:
            return {
                "credit_amount": 0,
                "credit_pct": 0,
                "reason": "SLA met",
                "actual_availability": actual_availability_pct,
                "sla_target": contract.sla_target_pct
            }
        
        # Find applicable credit tier
        applicable_tier = None
        for tier in sorted(contract.credit_schedule, key=lambda t: t.credit_pct, reverse=True):
            if actual_availability_pct >= tier.min_availability_pct:
                applicable_tier = tier
                break
        
        if applicable_tier is None:
            # Below all defined tiers — use highest credit
            applicable_tier = max(contract.credit_schedule, key=lambda t: t.credit_pct)
        
        credit_amount = contract.monthly_fee * (applicable_tier.credit_pct / 100)
        
        # Apply maximum cap (typically 50%)
        max_credit = contract.monthly_fee * 0.50
        credit_amount = min(credit_amount, max_credit)
        
        return {
            "customer_id": contract.customer_id,
            "customer_name": contract.customer_name,
            "sla_target_pct": contract.sla_target_pct,
            "actual_availability_pct": round(actual_availability_pct, 4),
            "monthly_fee": contract.monthly_fee,
            "credit_pct": applicable_tier.credit_pct,
            "credit_amount": round(credit_amount, 2),
            "credit_capped": credit_amount == max_credit,
            "credit_tier": f"{applicable_tier.min_availability_pct}% - {contract.sla_target_pct}%"
        }
    
    def process_all_credits_for_month(self, year: int, month: int) -> list:
        """
        Calculate credits for all enterprise customers for a given month.
        Run this on the 1st of each month for the previous month.
        """
        results = []
        
        for contract in self.get_enterprise_contracts():
            # Get actual availability from monitoring data
            actual_availability = self.monitoring.get_monthly_availability(
                customer_id=contract.customer_id,
                year=year,
                month=month
            )
            
            credit = self.calculate_monthly_credit(contract, actual_availability)
            results.append(credit)
            
            if credit["credit_amount"] > 0:
                # Apply credit to billing system
                self.billing.apply_credit(
                    customer_id=contract.customer_id,
                    amount=credit["credit_amount"],
                    description=f"SLA credit for {year}-{month:02d}: {actual_availability:.4f}% availability",
                    reference=f"sla-credit-{year}-{month:02d}"
                )
                
                # Notify customer
                self.notify_customer_of_credit(contract, credit, year, month)
        
        return results

Proactive vs Reactive Credit Application

The way credits are initiated has a significant impact on customer perception:

| Approach | Customer Experience | Trust Impact | |---|---|---| | Customer must request credits | Customers who don't know to ask don't get credits; creates adversarial relationship | Negative | | Provider applies credits when customer complains | Reactive; customers feel they had to fight for compensation | Neutral | | Provider automatically calculates and applies credits | Customer receives credits without asking; shows confidence in commitments | Positive | | Provider notifies customer proactively before next invoice | Best practice; customer sees credit before seeing invoice | Strongly positive |

Recommendation: Automate credit calculation and application. Notify customers proactively. This signals that you take your commitments seriously.

Credit Communication Template

When applying an SLA credit, communicate proactively:

Subject: SLA Credit Applied to Your Account — [Month]

[First Name],

Your service experienced a brief disruption on [date] that resulted in 
[downtime duration] of unavailability. Your actual monthly availability 
was [X]%, which fell below our committed [SLA target]%.

We've automatically applied a service credit of [credit amount] to 
your account. This credit will appear on your [next month] invoice.

**What happened:**
[2-3 sentence plain-language explanation]

**What we've done to prevent recurrence:**
[Specific action items]

**Your account details:**
- Monthly service fee: $[amount]
- SLA commitment: [X]% availability
- Actual availability: [X]%
- Credit amount: $[amount] ([X]% of monthly fee)

For a detailed incident report, please visit [link].

We apologize for the disruption and appreciate your continued trust.

[Name]
Customer Success

Handling Disputed Credits

When customers dispute credit calculations:

class CreditDisputeHandler:
    """
    Handle SLA credit disputes with a clear, documented process.
    """
    
    def process_dispute(self, customer_id, disputed_month, customer_claim):
        """
        Compare customer's claimed downtime vs provider's measured downtime.
        """
        # Get provider's monitoring data
        provider_data = self.monitoring.get_monthly_data(customer_id, disputed_month)
        
        # Get customer's submitted evidence
        customer_data = customer_claim.get("monitoring_data")
        
        dispute_analysis = {
            "provider_availability_pct": provider_data.availability_pct,
            "customer_claimed_availability_pct": customer_claim.get("claimed_availability"),
            "discrepancy_pct": abs(
                provider_data.availability_pct - 
                (customer_claim.get("claimed_availability") or 0)
            )
        }
        
        # Common reasons for discrepancy
        potential_causes = []
        
        if dispute_analysis["discrepancy_pct"] > 0.5:
            potential_causes.append("Significant discrepancy — investigate measurement methodology")
        
        if customer_data and customer_data.get("measurement_location") == "customer_network":
            potential_causes.append("Customer measurement includes their own network latency/failures")
        
        if customer_data and customer_data.get("includes_planned_maintenance"):
            potential_causes.append("Customer measurement may include excluded maintenance windows")
        
        return {
            "dispute_analysis": dispute_analysis,
            "potential_causes": potential_causes,
            "resolution_path": self.determine_resolution_path(dispute_analysis),
            "documentation": {
                "provider_monitoring_logs": provider_data.raw_checks,
                "contract_measurement_definition": self.get_contract_measurement_clause(customer_id),
                "applicable_exclusions": self.get_applicable_exclusions(customer_id, disputed_month)
            }
        }
    
    def determine_resolution_path(self, dispute_analysis):
        """
        Determine the appropriate resolution for a credit dispute.
        """
        discrepancy = dispute_analysis["discrepancy_pct"]
        
        if discrepancy < 0.1:
            return "accept_customer_claim"  # Small discrepancy, customer benefit of doubt
        elif discrepancy < 0.5:
            return "negotiate_middle_ground"  # Use average of both measurements
        else:
            return "detailed_reconciliation_required"  # Need detailed log comparison

Credit Cap Considerations

Maximum credit caps protect business viability but should be set thoughtfully:

## Credit Cap Design Considerations

### Standard Practice: 50% Monthly Fee Cap
Rationale: 
- Preserves business viability during severe outages
- Still provides meaningful compensation
- Customers can pursue other remedies (cancellation, legal) for catastrophic failures

### Enterprise Negotiation: Higher Caps
Some enterprise customers negotiate higher caps:
- 100% of monthly fee (common for critical business systems)
- Multiple months of credit (for sustained outages)
- Direct refund rather than credit (for financial impact)

### What Caps Don't Cover
Credits compensate for the fee paid — not for:
- Customer revenue lost during outage
- Cost of workarounds implemented
- Staff time spent on outage impact

These consequential damages are typically excluded by contract.
If a customer's business is significantly impacted, they may pursue
breach of warranty claims regardless of credit caps.

### Setting Appropriate Caps
The cap should be:
- High enough to be meaningful compensation
- Low enough to not create existential risk from a single customer's credits
- Consistent with the risk profile of the service

Tracking Credit Trends

Monitor credit issuance as a reliability health metric:

def analyze_credit_trends(credits, months=12):
    """
    Analyze SLA credit issuance trends as a proxy for reliability health.
    Increasing credits → decreasing reliability.
    """
    monthly_totals = {}
    
    for credit in credits:
        month_key = credit["month"]
        if month_key not in monthly_totals:
            monthly_totals[month_key] = {
                "total_credits_issued": 0,
                "accounts_with_credits": 0,
                "largest_single_credit": 0
            }
        
        monthly_totals[month_key]["total_credits_issued"] += credit["credit_amount"]
        monthly_totals[month_key]["accounts_with_credits"] += 1
        monthly_totals[month_key]["largest_single_credit"] = max(
            monthly_totals[month_key]["largest_single_credit"],
            credit["credit_amount"]
        )
    
    # Calculate trends
    sorted_months = sorted(monthly_totals.keys())
    recent = sorted_months[-3:]  # Last 3 months
    earlier = sorted_months[-6:-3]  # 3 months before that
    
    recent_avg = sum(monthly_totals[m]["total_credits_issued"] for m in recent) / len(recent)
    earlier_avg = sum(monthly_totals[m]["total_credits_issued"] for m in earlier) / len(earlier) if earlier else 0
    
    trend = "increasing" if recent_avg > earlier_avg * 1.1 else "stable" if recent_avg > earlier_avg * 0.9 else "improving"
    
    return {
        "monthly_data": monthly_totals,
        "trend": trend,
        "recent_3mo_avg_credits": round(recent_avg, 2),
        "earlier_3mo_avg_credits": round(earlier_avg, 2),
        "alert": trend == "increasing"
    }

Conclusion

SLA credits work best as a trust mechanism, not just a financial liability. Providers who automate credit calculation, apply credits proactively, and communicate clearly about what happened and what's being fixed retain customers through SLA breaches far better than providers who make customers fight for compensation. The underlying requirement for all of this is accurate, independent monitoring data — you need reliable availability measurements to calculate credits correctly, defend against disputes, and build the credibility that makes proactive credit application feel genuine rather than strategic. AzMonitor provides the external monitoring record that serves as the objective availability baseline for these calculations.

Tags:SLA creditsservice creditsSLA breachcustomer compensation
Back to blog
A
AzMonitor Team
The AzMonitor team writes guides based on experience monitoring millions of endpoints daily across 10,000+ customer environments. Our expertise covers uptime monitoring, SRE practices, and reliability engineering.
Try AzMonitor free

3 monitors free forever · No credit card needed · Set up in 2 minutes

Start monitoring free →