Webapp-Wartung & Support: Kosten, SLA & was wirklich nötig ist
Wartung & Betrieb

Webapp-Wartung & Support: Kosten, SLA & was wirklich nötig ist

Carola Schulte
Invalid Date
13 min

“Die App läuft doch, warum sollen wir monatlich zahlen?” Diese Frage höre ich regelmäßig. Die Antwort kommt meist 6 bis 12 Monate später, wenn PHP veraltet ist, Security-Patches fehlen und der Server unter Last zusammenbricht. Webapp-Wartung ist wie Zahnpflege: Ignorieren funktioniert eine Weile, aber die Rechnung kommt garantiert.

Executive Summary

WartungspaketMonatliche KostenEnthaltenFür wen geeignet
Basic500 bis 800 EuroSecurity-Updates, Monitoring, Backup-PrüfungKleine interne Tools
Standard1.000 bis 1.500 EuroBasic + Bug-Fixes, kleine Anpassungen, SLA 48hBusiness-kritische Apps
Premium2.000 bis 2.500 EuroStandard + 24/7 Monitoring, SLA 4h, On-CallMission-Critical, E-Commerce

ROI-Beispiel: 1.200 Euro/Monat Wartung vs. 45.000 Euro Notfall-Migration nach Security-Breach.

Was passiert ohne Wartung?

Die ersten 6 Monate: Alles läuft

Die App funktioniert, keine sichtbaren Probleme. Der Geschäftsführer fragt: “Warum zahlen wir Wartung?”

Monate 6 bis 12: Erste Warnsignale

  • PHP-Version veraltet (Security-Patches fehlen)
  • SSL-Zertifikat läuft unbemerkt ab
  • Datenbank wächst, keine Optimierung
  • Erste Performance-Einbrüche bei Lastspitzen

Monate 12 bis 18: Probleme häufen sich

  • Hoster kündigt Support für alte PHP-Version an
  • Backup funktioniert nicht mehr (niemand hat geprüft)
  • Externe APIs ändern sich, Integrationen brechen
  • Security-Scanner meldet kritische Schwachstellen

Monat 18+: Die Rechnung kommt

Real Case: Ein Kunde hatte 18 Monate keine Wartung. Dann:

  • SQL-Injection-Angriff über bekannte Schwachstelle
  • 48h Downtime, Datenverlust
  • DSGVO-Meldung an Behörde erforderlich
  • Notfall-Migration: 45.000 Euro
  • Verlorenes Kundenvertrauen: unbezahlbar

Mit 1.200 Euro/Monat Wartung wäre das nicht passiert.

Was gehört zur Wartung?

1. Security-Updates (kritisch)

// Security-Patch-Management
class SecurityUpdateService {
    private array $komponenten = [
        'php' => ['aktuell' => '8.3.x', 'minimum' => '8.1.x', 'eol' => '8.0.x'],
        'postgresql' => ['aktuell' => '16.x', 'minimum' => '14.x'],
        'composer_packages' => 'wöchentlich prüfen',
    ];

    public function pruefeUpdates(): array {
        $ergebnis = [];

        // PHP-Version prüfen
        $phpVersion = phpversion();
        if (version_compare($phpVersion, '8.1.0', '<')) {
            $ergebnis[] = [
                'komponente' => 'PHP',
                'status' => 'kritisch',
                'aktion' => 'Sofort updaten, EOL erreicht',
            ];
        }

        // Composer-Pakete auf Schwachstellen prüfen
        // composer audit --format=json
        $audit = shell_exec('composer audit --format=json 2>/dev/null');
        $vulnerabilities = json_decode($audit, true);

        if (!empty($vulnerabilities['advisories'])) {
            foreach ($vulnerabilities['advisories'] as $paket => $advisory) {
                $ergebnis[] = [
                    'komponente' => $paket,
                    'status' => 'schwachstelle',
                    'aktion' => 'Update auf sichere Version',
                ];
            }
        }

        return $ergebnis;
    }
}

Aufwand: 2 bis 4 Stunden/Monat Was passiert ohne: Bekannte Schwachstellen bleiben offen, Angriffsfläche wächst

2. Monitoring & Alerting

// Einfaches Health-Check-Endpoint
class HealthCheckController {
    public function __construct(
        private PDO $db,
        private Redis $redis
    ) {}

    public function check(): array {
        $status = ['status' => 'healthy', 'checks' => []];

        // Datenbank-Verbindung
        try {
            $this->db->query('SELECT 1');
            $status['checks']['database'] = 'ok';
        } catch (PDOException $e) {
            $status['status'] = 'unhealthy';
            $status['checks']['database'] = 'failed';
        }

        // Redis-Verbindung
        try {
            $this->redis->ping();
            $status['checks']['redis'] = 'ok';
        } catch (Exception $e) {
            $status['status'] = 'degraded';
            $status['checks']['redis'] = 'failed';
        }

        // Festplattenspeicher
        $freeSpace = disk_free_space('/');
        $totalSpace = disk_total_space('/');
        $usedPercent = (1 - $freeSpace / $totalSpace) * 100;

        if ($usedPercent > 90) {
            $status['status'] = 'warning';
            $status['checks']['disk'] = "kritisch: {$usedPercent}% belegt";
        } else {
            $status['checks']['disk'] = "ok: {$usedPercent}% belegt";
        }

        // Response-Header für Monitoring-Tools
        http_response_code($status['status'] === 'healthy' ? 200 : 503);

        return $status;
    }
}

Was überwachen:

  • Verfügbarkeit (Uptime)
  • Response-Zeiten
  • Error-Raten (5xx-Fehler)
  • Ressourcen (CPU, RAM, Disk)
  • SSL-Zertifikat-Ablauf
  • Datenbank-Verbindungen

Aufwand: Setup 4h, dann automatisiert Tools: UptimeRobot (kostenlos), Datadog, New Relic, eigenes Monitoring

3. Backup-Management

// Backup-Verifizierung
class BackupVerificationService {
    public function verifyBackup(string $backupPath): array {
        $ergebnis = [
            'datum' => date('Y-m-d H:i:s'),
            'pfad' => $backupPath,
            'checks' => [],
        ];

        // 1. Backup existiert
        if (!file_exists($backupPath)) {
            $ergebnis['status'] = 'failed';
            $ergebnis['checks']['existenz'] = 'Backup nicht gefunden';
            return $ergebnis;
        }

        // 2. Backup ist aktuell (max 24h alt)
        $alter = time() - filemtime($backupPath);
        if ($alter > 86400) {
            $ergebnis['checks']['alter'] = 'Warnung: älter als 24h';
        } else {
            $ergebnis['checks']['alter'] = 'ok';
        }

        // 3. Backup hat sinnvolle Größe
        $groesse = filesize($backupPath);
        $minGroesse = 1024 * 1024; // Min 1 MB
        if ($groesse < $minGroesse) {
            $ergebnis['checks']['groesse'] = 'Warnung: verdächtig klein';
        } else {
            $ergebnis['checks']['groesse'] = 'ok: ' . round($groesse / 1024 / 1024) . ' MB';
        }

        // 4. Restore-Test (monatlich)
        // In separater Test-Umgebung durchführen!

        $ergebnis['status'] = 'ok';
        return $ergebnis;
    }

    public function getBackupRetention(): array {
        return [
            'täglich' => '7 Tage aufbewahren',
            'wöchentlich' => '4 Wochen aufbewahren',
            'monatlich' => '12 Monate aufbewahren',
            'offsite' => 'Kopie an zweitem Standort',
        ];
    }
}

Aufwand: 1 bis 2 Stunden/Monat (Prüfung + Restore-Test) Was passiert ohne: Backup existiert, aber Restore funktioniert nicht (häufiger als gedacht)

4. Performance-Überwachung

// Slow-Query-Log auswerten
class PerformanceAnalyzer {
    public function analyzeSlowQueries(PDO $db): array {
        // PostgreSQL: pg_stat_statements aktivieren
        $stmt = $db->query("
            SELECT
                query,
                calls,
                total_exec_time / 1000 as total_seconds,
                mean_exec_time / 1000 as avg_seconds,
                rows
            FROM pg_stat_statements
            WHERE mean_exec_time > 100  -- > 100ms
            ORDER BY total_exec_time DESC
            LIMIT 10
        ");

        $slowQueries = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $empfehlungen = [];
        foreach ($slowQueries as $query) {
            if ($query['avg_seconds'] > 1) {
                $empfehlungen[] = [
                    'query' => substr($query['query'], 0, 100) . '...',
                    'durchschnitt' => round($query['avg_seconds'], 2) . 's',
                    'aufrufe' => $query['calls'],
                    'empfehlung' => 'Index prüfen, Query optimieren',
                ];
            }
        }

        return $empfehlungen;
    }

    public function checkTableBloat(PDO $db): array {
        // PostgreSQL: Aufgeblähte Tabellen finden
        $stmt = $db->query("
            SELECT
                schemaname || '.' || relname as tabelle,
                pg_size_pretty(pg_total_relation_size(relid)) as groesse,
                n_dead_tup as dead_tuples,
                last_vacuum,
                last_autovacuum
            FROM pg_stat_user_tables
            WHERE n_dead_tup > 10000
            ORDER BY n_dead_tup DESC
        ");

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

Monatliche Checks:

  • Slow Queries identifizieren
  • Index-Nutzung prüfen
  • Tabellen-Bloat (VACUUM)
  • Cache-Hit-Ratio

Aufwand: 2 bis 4 Stunden/Monat

5. Dependency-Updates

# Composer-Updates (PHP)
composer outdated --direct  # Zeigt veraltete Pakete
composer update --dry-run   # Simulation
composer update            # Update durchführen

# npm-Updates (Frontend, falls vorhanden)
npm outdated
npm update
// Automatisierte Dependency-Prüfung
class DependencyChecker {
    public function checkComposerPackages(): array {
        $composerLock = json_decode(
            file_get_contents('composer.lock'),
            true
        );

        $veraltete = [];
        foreach ($composerLock['packages'] as $package) {
            // Prüfe auf Security-Advisories
            // Prüfe auf Major-Updates
            // Prüfe auf EOL-Versionen
        }

        return $veraltete;
    }

    public function getUpdateStrategy(): array {
        return [
            'security' => 'Sofort (innerhalb 24h)',
            'bugfix' => 'Wöchentlich (minor versions)',
            'feature' => 'Monatlich (nach Test)',
            'major' => 'Quartalsweise (mit Migrationsplan)',
        ];
    }
}

Aufwand: 2 bis 4 Stunden/Monat Risiko ohne: Veraltete Dependencies mit bekannten Schwachstellen

SLA-Beispiele zum Kopieren

SLA Basic (500 bis 800 Euro/Monat)

Reaktionszeiten:

  • Kritisch (System nicht nutzbar): Reaktion innerhalb von 24 Stunden (Werktage)
  • Hoch (Funktion eingeschränkt): Reaktion innerhalb von 48 Stunden (Werktage)
  • Normal (Fehler ohne Workaround): Reaktion innerhalb von 5 Werktagen

Leistungen:

  • Security-Updates für PHP, PostgreSQL, Betriebssystem
  • Monatliche Backup-Prüfung
  • Uptime-Monitoring mit E-Mail-Alert
  • Bis zu 2 Stunden Bug-Fixes pro Monat (nicht übertragbar)

Nicht enthalten:

  • Feature-Entwicklung
  • Wochenend- und Feiertagssupport
  • Performance-Optimierung

SLA Standard (1.000 bis 1.500 Euro/Monat)

Reaktionszeiten:

  • Kritisch (System nicht nutzbar): Reaktion innerhalb von 4 Stunden, Fix innerhalb von 24 Stunden
  • Hoch (Funktion eingeschränkt): Reaktion innerhalb von 8 Stunden, Fix innerhalb von 48 Stunden
  • Normal (Fehler ohne Workaround): Reaktion innerhalb von 24 Stunden, Fix innerhalb von 5 Werktagen

Leistungen:

  • Alles aus Basic
  • Proaktives Monitoring (Response-Zeiten, Error-Rates)
  • Monatlicher Performance-Report
  • Bis zu 5 Stunden Bug-Fixes/kleine Anpassungen pro Monat
  • Quartalsweiser Restore-Test
  • Dependency-Updates mit Changelog

Nicht enthalten:

  • Feature-Entwicklung (separat abrechenbar)
  • 24/7-Support

SLA Premium (2.000 bis 2.500 Euro/Monat)

Reaktionszeiten:

  • Kritisch (System nicht nutzbar): Reaktion innerhalb von 1 Stunde, Fix innerhalb von 4 Stunden (24/7)
  • Hoch (Funktion eingeschränkt): Reaktion innerhalb von 2 Stunden, Fix innerhalb von 8 Stunden
  • Normal: Reaktion innerhalb von 4 Stunden, Fix innerhalb von 24 Stunden

Leistungen:

  • Alles aus Standard
  • 24/7 Monitoring mit Telefon-Eskalation
  • On-Call-Bereitschaft (Rufbereitschaft)
  • Bis zu 10 Stunden Bug-Fixes/Anpassungen pro Monat
  • Monatlicher Restore-Test
  • Proaktive Performance-Optimierung
  • Dedizierter Ansprechpartner

Verfügbarkeitsgarantie: 99,5% Uptime (max. 3,6h Downtime/Monat)

Kostenvergleich: Wartung vs. Keine Wartung

Szenario 1: Alles läuft gut (3 Jahre)

PostenMit WartungOhne Wartung
Monatliche Kosten1.200 Euro x 36 = 43.200 Euro0 Euro
Notfall-Einsätze0 Euro8.000 Euro (2x jährlich)
PHP-Migration (EOL)Inkludiert12.000 Euro
Performance-ProblemeProaktiv behoben6.000 Euro Notfall-Optimierung
Gesamt43.200 Euro42.000 Euro

Fast gleich? Ja, aber: Bei “Ohne Wartung” ist das Risiko nicht eingepreist.

Szenario 2: Security-Incident

PostenMit WartungOhne Wartung
3 Jahre Wartung43.200 Euro0 Euro
Security-BreachVerhindert45.000 Euro Notfall-Response
Downtime (48h)0 Euro15.000 Euro Umsatzausfall
DSGVO-Strafe0 Euro10.000 bis 50.000 Euro
Reputationsschaden0 EuroUnbezifferbar
Gesamt43.200 Euro70.000 bis 110.000 Euro

Was Sie selbst machen können

Tägliche Checks (5 Minuten)

# Einfaches Health-Check-Skript für Cronjob
#!/bin/bash

URL="https://ihre-app.de/health"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $URL)

if [ $RESPONSE != "200" ]; then
    echo "ALARM: Health-Check fehlgeschlagen (HTTP $RESPONSE)" | \
    mail -s "App-Alarm" admin@firma.de
fi

Wöchentliche Checks (30 Minuten)

  • Error-Logs prüfen (ungewöhnliche Muster?)
  • Disk-Usage prüfen (> 80% kritisch)
  • Backup-Datum prüfen (aktuell?)
  • SSL-Zertifikat prüfen (Ablauf in < 30 Tagen?)

Monatliche Checks (2 Stunden)

  • Security-Updates verfügbar?
  • Composer/npm outdated prüfen
  • Slow-Query-Log analysieren
  • Uptime-Report reviewen
  • Backup-Restore testen (in Staging)

Wartungsvertrag: Worauf achten

Must-Haves im Vertrag

1. Klare Definition von “Bug” vs. “Feature”:

“Als Bug gilt ein Verhalten der Software, das von der dokumentierten Spezifikation abweicht. Neue Funktionalitäten oder Änderungswünsche gelten als Feature und werden separat beauftragt.”

2. Reaktionszeit vs. Lösungszeit:

“Reaktionszeit bezeichnet die Zeit bis zur ersten qualifizierten Rückmeldung. Lösungszeit bezeichnet die Zeit bis zur Behebung des Problems oder Bereitstellung eines Workarounds.”

3. Definition der Prioritäten:

class TicketPrioritaet {
    public const KRITISCH = [
        'definition' => 'System nicht nutzbar, keine Workaround möglich',
        'beispiele' => ['Login nicht möglich', 'Datenbank nicht erreichbar', 'Komplettausfall'],
        'reaktion' => '4h',
        'loesung' => '24h',
    ];

    public const HOCH = [
        'definition' => 'Wichtige Funktion eingeschränkt, Workaround existiert',
        'beispiele' => ['Export fehlerhaft', 'Performance-Einbruch', 'Teilausfall'],
        'reaktion' => '8h',
        'loesung' => '48h',
    ];

    public const NORMAL = [
        'definition' => 'Fehler ohne kritische Auswirkung',
        'beispiele' => ['Darstellungsfehler', 'Falsches Datumsformat', 'Kleinere Bugs'],
        'reaktion' => '24h',
        'loesung' => '5 Werktage',
    ];
}

4. Stundenkontingent:

“Das monatliche Kontingent von X Stunden verfällt am Monatsende und ist nicht übertragbar. Nicht genutzte Stunden werden nicht erstattet. Zusätzliche Stunden werden mit Y Euro/Stunde abgerechnet.”

Red Flags im Vertrag

  • “Best Effort” ohne konkrete Zeiten: Bedeutet nichts
  • Keine Definition von Prioritäten: Führt zu Diskussionen
  • Automatische Verlängerung ohne Kündigungsrecht: Prüfen!
  • Keine Regelung für Preisanpassungen: Jährliche Erhöhung vereinbaren

Checkliste: Brauche ich Wartung?

Ja, unbedingt (Standard oder Premium)

  • Die App ist geschäftskritisch (Ausfall kostet > 1.000 Euro/Stunde)
  • Personenbezogene Daten werden verarbeitet (DSGVO)
  • Externe Nutzer (Kunden, Partner) arbeiten damit
  • Integration mit anderen Systemen (API-Abhängigkeiten)
  • Mehr als 100 aktive Nutzer

Ja, mindestens Basic

  • Die App wird regelmäßig genutzt
  • Keine internen Ressourcen für Updates vorhanden
  • PHP/PostgreSQL-Version älter als 2 Jahre

Vielleicht verzichtbar

  • Rein internes Tool mit < 10 Nutzern
  • Kein Internet-Zugriff (nur Intranet)
  • Eigene IT-Abteilung mit PHP/PostgreSQL-Know-how
  • Niedriger Schaden bei Ausfall

Fazit: Wartung ist Versicherung

Webapp-Wartung ist keine optionale Luxusleistung. Sie ist eine Versicherung gegen vorhersehbare Risiken. Die Frage ist nicht “ob” etwas passiert, sondern “wann”.

Meine Empfehlung:

App-TypEmpfohlenes PaketMonatliche Kosten
Internes Tool, < 50 UserBasic500 bis 800 Euro
Business-App, 50 bis 500 UserStandard1.000 bis 1.500 Euro
E-Commerce, > 500 UserPremium2.000 bis 2.500 Euro
Mission-Critical, 24/7Premium + On-Call2.500+ Euro

Die billigste Wartung ist die, die Probleme verhindert, bevor sie entstehen.


Sie haben eine bestehende Webapp ohne Wartungsvertrag? In einem kostenlosen 30-Minuten-Check analysiere ich den Ist-Zustand und empfehle das passende Wartungspaket.

Carola Schulte

Über Carola Schulte

Software-Architektin mit 25+ Jahren Erfahrung. Spezialisiert auf robuste Business-Apps mit PHP/PostgreSQL, Security-by-Design und DSGVO-konforme Systeme. 1,8M+ Lines of Code in Produktion.

Projekt im Kopf?

Lassen Sie uns besprechen, wie ich Ihre Anforderungen umsetzen kann – kostenlos und unverbindlich.

Kostenloses Erstgespräch