DevOps & Scaling

Arquitetura de solução CAPTCHA multirregional com CaptchaAI

Workers de CAPTCHA presos numa única região empurram cada requisição para o outro lado do mundo — e se essa região cai, o pipeline inteiro para. A arquitetura multirregional resolve os dois problemas de uma vez: coloca workers perto dos sites-alvo, reduzindo o tempo de ida e volta da API, e mantém o serviço de pé quando uma região específica falha.

Este guia mostra como montar a arquitetura com a CaptchaAI: roteamento por região, workers com Docker Compose e Terraform, monitoramento de saúde e failover automático.

Quando vale a pena distribuir workers por região

Situação Região única Multirregião
Sites-alvo concentrados em um país Suficiente Complexidade desnecessária
Sites-alvo espalhados pelo mundo 100–300 ms de latência extra Latência local em cada região
SLA de 99,9% de disponibilidade Difícil sem redundância Redundância natural
Residência de dados regulatória (LGPD/GDPR) Difícil de comprovar Processamento local por região
< 1.000 tarefas/hora Sem necessidade Complexidade desnecessária
> 10.000 tarefas/hora Esbarra em limites de escala Distribui a carga

Antes de decidir, confirme (LGPD/GDPR: envolva o compliance):

  • Onde ficam a maioria dos sites-alvo
  • Exigência de residência de dados
  • Volume acima de 10.000 tarefas/hora

Visão geral da arquitetura

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

Cada região roda seu próprio conjunto de workers, todos com a mesma chave de API da CaptchaAI, enviando resultados a um armazenamento central — sem chave por região, só métricas.

Implante workers por região

Worker em Python com reconhecimento de região

O worker abaixo resolve o CAPTCHA e devolve a região de origem junto com o resultado, para medir latência por região nas suas métricas:

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}

Roteador de tarefas

Encaminhe cada tarefa para a fila mais próxima do site de destino:

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

Configuração de infraestrutura

O Terraform provisiona a frota de workers; o Docker Compose simula tudo localmente antes do deploy.

Estrutura básica do Terraform

# 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"
}

Docker Compose para simular multirregião localmente

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

Monitoramento de saúde por região

Um checador simples por região, em 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);

Esses dados alimentam a política de failover a seguir.

Estratégia e política de failover

Quando uma região fica indisponível, redistribua as tarefas dela entre as regiões saudáveis:

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

Regras para essa política não virar caos operacional:

  • Pare de enviar tarefas novas para uma região degradada assim que latência, erros ou saúde do proxy passarem do limite da política.
  • Drene o tráfego em andamento aos poucos — não derrube filas e sessões de uma vez.
  • Só volte a rotear tarefas para a região depois que ela passar pelos mesmos critérios de saúde do failover.

Considerações de custo

Componente Fator de custo Otimização
Instâncias de worker Computação por região Auto-scaling para zero quando ocioso
Transferência de dados entre regiões US$ 0,02/GB entre regiões Minimize o tamanho da carga útil do resultado
Filas SQS Preço por requisição Agrupe mensagens em lote sempre que possível
API da CaptchaAI Mesmo custo, qualquer região Sem prêmio multirregional — a tarifa não muda de onde o worker roda

Erros comuns e como corrigir

  • Uma região é consistentemente mais lenta. Causa: distância até os servidores da CaptchaAI. Compare com a latência de base antes de tratar como problema.
  • O roteamento manda tudo para uma única região. Causa: regra de domínio abrangente demais. Adicione regras mais granulares.
  • O failover não dispara. Causa: o endpoint de saúde não responde. Confirme que ele fica separado da lógica do worker.
  • O saldo da chave de API cai mais rápido do que o esperado. Causa: todas as regiões compartilham a mesma chave. Normal — monitore o uso agregado por região.

Perguntas frequentes

Preciso de uma chave de API diferente para cada região?

Não. Uma única chave da CaptchaAI funciona globalmente — acompanhe o consumo por região com as suas próprias métricas, não com múltiplas chaves.

O uso de várias regiões deixa o plano da CaptchaAI mais caro?

  • Não diretamente: cobrança é por thread contratada, não por região
  • BASIC: US$ 15/mês, 5 threads — ADVANCE: US$ 90/mês, 50 threads
  • Custo extra da multirregião é infraestrutura, não API

Faz sentido rodar um worker em sa-east-1 para sites brasileiros?

Sim, se a maior parte do tráfego mira sites no Brasil:

  • RTT menor que us-east-1
  • Mesma lógica de latência deste guia

Quantas regiões preciso para ter alta disponibilidade de verdade?

Duas regiões em áreas geográficas diferentes (EUA + UE, por exemplo) já dão HA básica. Três regiões (EUA + UE + Ásia) cobrem disponibilidade global.

Artigos relacionados

Veja também a arquitetura do balanceador de carga da CaptchaAI e a arquitetura da API de resolução de CAPTCHA.

Próximos passos

Pegue sua chave de API da CaptchaAI e comece a distribuir workers entre regiões. Veja também 10.000 tarefas por hora, desempenho por região e workers com escalonamento automático.

Os comentários estão desativados para este artigo.