Wartung einer Webanwendung: Was sie kostet und was drin sein muss
Wartung & Betrieb

Wartung einer Webanwendung: Was sie kostet und was drin sein muss

Carola Schulte
18. August 2025 · aktualisiert 25. September 2026
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

Häufige Fragen

Was kostet die Wartung einer Webanwendung?
Aus meinen Wartungspaketen: Basis 500 bis 800 Euro im Monat mit Sicherheitsupdates, Monitoring und Backup-Prüfung. Standard 1.000 bis 1.500 Euro mit Fehlerbehebung, kleinen Anpassungen und Reaktionszeit 48 Stunden. Premium 2.000 bis 2.500 Euro mit Überwachung rund um die Uhr, Reaktionszeit 4 Stunden und Bereitschaft.
Was passiert, wenn eine Webanwendung nicht gewartet wird?
Sicherheitslücken in Bibliotheken und Server bleiben offen, Backups werden nicht geprüft, bis man sie braucht, und kleine Fehler sammeln sich, bis ein Ausfall kommt. Das Rechenbeispiel im Beitrag: 1.200 Euro Wartung im Monat gegenüber 45.000 Euro für eine Notfall-Migration nach einem Sicherheitsvorfall.
Was gehört in einen Wartungsvertrag?
Der Umfang (Updates, Monitoring, Backups, Fehlerbehebung), die Reaktionszeiten je Schweregrad, die Erreichbarkeit, die Abgrenzung zu neuen Funktionen, die abgerechnet werden, und die Regeln für Kündigung und Übergabe des Codes. Beispiele zum Kopieren stehen im Abschnitt zu den SLA.

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

Weitere interessante Artikel

Webanwendung entwickeln lassen: Kosten 2026

Was kostet es, eine Webanwendung entwickeln zu lassen?

Backup ohne Restore-Test ist kein Backup

Ein Backup, das nie zurückgespielt wurde, ist eine Hoffnung.