DevOps & Skalierung

Multiregionale CAPTCHA-Lösungsarchitektur mit CaptchaAI

Eine Multi-Region-Architektur brauchen Sie genau dann, wenn Ihre Zielseiten über mehrere Kontinente verteilt sind oder wenn harte Verfügbarkeitszusagen gelten. Sitzen die CAPTCHA-Worker näher an den Zielstandorten, sinkt die Roundtrip-Zeit zur API, und ein regionaler Ausfall legt nicht die gesamte Pipeline lahm.

Der Aufwand lohnt sich aber nur, wenn Geografie wirklich Teil des Problems ist. Liegen Ihre Ziele in einer einzigen Region und bleibt die Last moderat, erhöht Multi-Region zunächst vor allem die Betriebs- und Monitoring-Komplexität.

Wann sich Multi-Region wirklich lohnt

Frage Antwort „ja" Antwort „nein"
Zielseiten auf mehreren Kontinenten? Regionale Verteilung ist plausibel Eine Region genügt meist
Harte Uptime- oder Failover-Vorgaben? Multi-Region lohnt sich Halten Sie das Design schlank
Müssen Daten regional bleiben (DSGVO)? Regionale Trennung einplanen Zusätzliche Regionen oft unnötig
Ist das Volumen noch gering? Erst eine Region stabilisieren und messen Nicht vorschnell ausbauen

Architekturüberblick

                    [Task Router]
                    (Route53 / Load Balancer)
                    ↙        ↓        ↘
        [US-East]      [EU-West]     [AP-Southeast]
        Workers        Workers        Workers
            ↓              ↓              ↓
        [CaptchaAI API] ← shared API key
            ↓              ↓              ↓
        [Central DB / Queue]
        (Results aggregation)

Jede Region betreibt eigene, unabhängige Worker. Alle nutzen denselben CaptchaAI-API-Schlüssel und schreiben ihre Ergebnisse in einen zentralen Speicher. Ein Task-Router verteilt Aufgaben nach Zielgeografie.

Einzelne Region oder Multi-Region im direkten Vergleich

Situation Einzelne Region Multi-Region
Zielseiten in einem Land Ausreichend Überdimensioniert
Globale Zielseiten 100–300 ms zusätzliche Latenz Lokale Latenz je Region
99,9 % Verfügbarkeit gefordert Schwer einzuhalten Natürliche Redundanz
Regulatorische Datenresidenz Nicht erfüllbar Lokale Verarbeitung
< 1.000 Aufgaben/Stunde Ausreichend Unnötige Komplexität
> 10.000 Aufgaben/Stunde Skalierungsgrenzen Verteilt die Last

Für DACH-Teams ist die mittlere Zeile oft der Auslöser: Ein Worker in eu-central-1 (Frankfurt) auf Hetzner oder IONOS hält die Latenz für .de-Ziele niedrig.

DSGVO und Datenverarbeitung im DACH-Raum

Sobald CAPTCHA-Worker mit personenbezogenen Daten in Berührung kommen – und dazu zählen bereits IP-Adressen –, wird die Region zur Compliance-Frage. Ein Worker in eu-central-1 verarbeitet Anfragen für .de-Ziele innerhalb der EU, was die Argumentation gegenüber der eigenen Datenschutzabteilung deutlich vereinfacht.

Multi-Region ist dabei kein Freibrief. Die regionale Trennung hilft nur, wenn der gesamte Datenfluss dazu passt:

  • Task-Router und zentrale Ergebnis-Queue ebenfalls in der EU-Region betreiben, nicht nur die Worker.
  • Logs und Monitoring-Daten mit IP-Bezug in derselben Region halten.
  • Die Rechtsgrundlage für die Verarbeitung eigenständig prüfen – CaptchaAI trifft dazu keine Zusagen.

Hinweis: Regionale Verarbeitung ist eine technische Maßnahme, kein Ersatz für eine datenschutzrechtliche Bewertung Ihres konkreten Workflows.

Regionale Worker bereitstellen

Python-Worker (regionsbewusst)

import os
import time
import requests

API_KEY = os.environ["CAPTCHAAI_API_KEY"]
REGION = os.environ.get("WORKER_REGION", "us-east-1")
RESULT_QUEUE_URL = os.environ["RESULT_QUEUE_URL"]


def solve_captcha(task):
    """Solve CAPTCHA and tag with region metadata."""
    start = time.time()

    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": task["method"],
        "googlekey": task["sitekey"],
        "pageurl": task["pageurl"],
        "json": 1
    })
    data = resp.json()

    if data.get("status") != 1:
        return {
            "task_id": task["task_id"],
            "error": data.get("request"),
            "region": REGION
        }

    captcha_id = data["request"]

    for _ in range(60):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": captcha_id, "json": 1
        }).json()

        if result.get("status") == 1:
            return {
                "task_id": task["task_id"],
                "solution": result["request"],
                "region": REGION,
                "duration": time.time() - start,
                "api_latency_ms": round((time.time() - start) * 1000)
            }
        if result.get("request") != "CAPCHA_NOT_READY":
            return {
                "task_id": task["task_id"],
                "error": result.get("request"),
                "region": REGION
            }

    return {"task_id": task["task_id"], "error": "TIMEOUT", "region": REGION}

Jeder Worker liest seine Region aus WORKER_REGION und hängt sie an jedes Ergebnis. So lassen sich Lösungszeit und Fehlerquote sauber pro Region auswerten.

Task-Router

Leiten Sie jede Aufgabe an die Region weiter, die dem Zielstandort am nächsten liegt:

from urllib.parse import urlparse

# Region mapping by target site TLD/domain
REGION_MAP = {
    ".co.uk": "eu-west-1",
    ".de": "eu-central-1",
    ".fr": "eu-west-3",
    ".jp": "ap-northeast-1",
    ".com.au": "ap-southeast-2",
    ".com": "us-east-1",  # Default
}

REGION_QUEUES = {
    "us-east-1": "sqs://captcha-tasks-us-east",
    "eu-west-1": "sqs://captcha-tasks-eu-west",
    "ap-southeast-1": "sqs://captcha-tasks-ap-southeast",
}


def route_task(task):
    """Route task to the closest regional queue."""
    domain = urlparse(task["pageurl"]).netloc

    target_region = "us-east-1"  # Default
    for suffix, region in REGION_MAP.items():
        if domain.endswith(suffix):
            target_region = region
            break

    queue = REGION_QUEUES.get(target_region, REGION_QUEUES["us-east-1"])
    send_to_queue(queue, task)
    return target_region

Die Zuordnung über die Top-Level-Domain ist bewusst simpel: .de landet in Frankfurt, alles Übrige fällt auf die US-Standardregion zurück.

Infrastruktur mit Terraform und Docker

Terraform-Skelett

# Define regions
variable "regions" {
  default = ["us-east-1", "eu-west-1", "ap-southeast-1"]
}

# Deploy worker fleet per region
module "captcha_workers" {
  for_each = toset(var.regions)
  source   = "./modules/captcha-worker"

  region              = each.key
  worker_count        = var.workers_per_region
  api_key_secret_arn  = aws_secretsmanager_secret.captchaai_key.arn
  task_queue_arn      = aws_sqs_queue.tasks[each.key].arn
  result_queue_arn    = aws_sqs_queue.results.arn
}

# SQS queue per region for task intake
resource "aws_sqs_queue" "tasks" {
  for_each = toset(var.regions)
  name     = "captcha-tasks-${each.key}"
}

# Central result queue
resource "aws_sqs_queue" "results" {
  name = "captcha-results-central"
}

Eine Warteschlange pro Region nimmt Aufgaben entgegen, eine zentrale Warteschlange sammelt die Ergebnisse ein; der API-Schlüssel liegt im Secrets Manager.

Docker Compose (lokale Simulation mehrerer Regionen)

version: "3.8"
services:
  worker-us:
    build: ./worker
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
      - WORKER_REGION=us-east-1
      - TASK_QUEUE=redis://redis:6379/0
    depends_on:

      - redis

  worker-eu:
    build: ./worker
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
      - WORKER_REGION=eu-west-1
      - TASK_QUEUE=redis://redis:6379/1

  worker-ap:
    build: ./worker
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
      - WORKER_REGION=ap-southeast-1
      - TASK_QUEUE=redis://redis:6379/2

  redis:
    image: redis:7-alpine

So testen Sie Routing und Failover lokal, bevor echte Regionen Kosten verursachen.

Health-Monitoring pro Region

JavaScript

const axios = require("axios");

const REGIONS = ["us-east-1", "eu-west-1", "ap-southeast-1"];

async function checkRegionHealth() {
  const health = {};

  for (const region of REGIONS) {
    const endpoint = `https://${region}.workers.example.com/health`;
    try {
      const start = Date.now();
      const resp = await axios.get(endpoint, { timeout: 5000 });
      health[region] = {
        status: "healthy",
        latencyMs: Date.now() - start,
        activeWorkers: resp.data.activeWorkers,
        queueDepth: resp.data.queueDepth,
      };
    } catch (err) {
      health[region] = { status: "unhealthy", error: err.message };
    }
  }

  return health;
}

// Periodic health check
setInterval(async () => {
  const health = await checkRegionHealth();
  console.table(health);
}, 60000);

Der Health-Check fragt jede Region im Minutentakt ab und erfasst Latenz, aktive Worker und Warteschlangentiefe.

Failover-Strategie

Fällt eine Region aus, verteilen Sie ihre Aufgaben auf die verbleibenden:

def failover_check(region_health):
    """Redirect tasks from unhealthy regions."""
    healthy_regions = [
        r for r, h in region_health.items()
        if h["status"] == "healthy"
    ]

    if not healthy_regions:
        raise RuntimeError("All regions unhealthy")

    redirects = {}
    for region, health in region_health.items():
        if health["status"] == "unhealthy":
            # Pick the healthy region with lowest queue depth
            target = min(
                healthy_regions,
                key=lambda r: region_health[r].get("queue_depth", 0)
            )
            redirects[region] = target
            print(f"Failover: {region} → {target}")

    return redirects

Die Logik wählt für jede gestörte Region die gesunde Region mit der geringsten Warteschlangentiefe. Sind alle Regionen gestört, bricht die Funktion bewusst mit einem Fehler ab, statt Aufgaben ins Leere zu routen.

Kostenüberlegungen

Komponente Kostenfaktor Optimierung
Worker-Instanzen Compute je Region Im Leerlauf automatisch auf 0 skalieren
Regionsübergreifender Datentransfer 0,02 $/GB zwischen Regionen Ergebnis-Payload klein halten
SQS-Warteschlangen Preis pro Anfrage Nachrichten bündeln, wo möglich
CaptchaAI-API Gleiche Kosten unabhängig von der Region Kein Aufpreis für Multi-Region

CaptchaAI rechnet unabhängig vom Standort des Workers dieselben Tarife ab – die Mehrkosten entstehen ausschließlich in der Infrastruktur. Da CaptchaAI Thread-basiert abrechnet (unbegrenzte Lösungen pro Thread, ab BASIC mit 15 $/Monat und 5 Threads), teilen sich alle Regionen dasselbe Thread-Kontingent.

Fehlerbehebung

Problem Ursache Lösung
Eine Region ist dauerhaft langsamer Distanz zu den CaptchaAI-Servern Basislatenz vergleichen – kann erwartbar sein
Routing schickt alles in eine Region Domainbasierte Regeln zu grob Feinere Regeln nach Hostname ergänzen
Failover greift nicht Health-Endpunkt antwortet nicht Health-Pfad von der Worker-Logik trennen
Guthaben sinkt schneller als erwartet Alle Regionen teilen einen Schlüssel Erwartbar – Gesamtverbrauch zentral überwachen

Schrittweiser Aufbau ohne Big Bang

Eine Multi-Region-Architektur muss nicht in einem Schritt entstehen. Bewährt hat sich ein schrittweises Vorgehen:

  1. Eine Region sauber stabilisieren und Basislatenz sowie Erfolgsquote messen.
  2. Eine zweite Region auf einem anderen Kontinent ergänzen und das Failover zunächst im Docker-Compose-Setup lokal testen.
  3. Das TLD-basierte Routing aktivieren und den Anteil der Aufgaben pro Region beobachten.
  4. Erst danach eine dritte Region ergänzen, wenn Latenz oder Verfügbarkeit es rechtfertigen.

So bleibt jeder Schritt messbar, und die Betriebskomplexität wächst nur dann, wenn sie einen konkreten Nutzen bringt.

Häufige Fragen

Wie viele Regionen brauche ich für Hochverfügbarkeit?

Zwei Regionen in unterschiedlichen Räumen (z. B. USA + EU) genügen für eine solide Grundabsicherung; erst ein dritter Standort in Asien deckt weltweite Verfügbarkeit ab.

Wie route ich Aufgaben für .de-Ziele nach Frankfurt?

Über die TLD: Im REGION_MAP-Dictionary zeigt .de auf eu-central-1. Der Router prüft die Domain der pageurl und legt die Aufgabe in die passende regionale Warteschlange.

Ist ein Multi-Region-Setup automatisch DSGVO-konform?

Nein, das hängt von Ihrem Datenfluss ab, nicht von CaptchaAI. Regionale Trennung kann helfen, personenbezogene Daten wie IP-Adressen lokal zu verarbeiten, ersetzt aber keine eigene Prüfung der Rechtsgrundlage.

Wie überwache ich den Thread-Verbrauch über alle Regionen hinweg?

Zentral, nicht pro Region. Da alle Regionen denselben API-Schlüssel und damit dasselbe Thread-Kontingent teilen, zählt nur der aggregierte Verbrauch. Erfassen Sie die Lösungen über die Region-Metadaten aus jedem Worker und summieren Sie sie im zentralen Speicher.


Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.