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.