// BLUEPRINT · ENGENHARIA REAL · ATLASSIAN 8 ANOS

COMO SE CONSTRÓI UMA
PLATAFORMA
QUE SE MANTÉM POR 8 ANOS.

O passo a passo destilado da infraestrutura de borda da Atlassian: ~2.000 proxies em ~13 regiões, servindo Jira, Confluence, Bitbucket e Status Page, com milhares de devs provisionando load balancing sozinhos.

“Crie a oportunidade de centralizar a lógica e resolver as preocupações cedo na cadeia de requisições.”
10passos de arquitetura
~2000proxies pré-provisionados
13regiões em produção
Começar pelo passo 01 ›

// CONTEXTO

Um blueprint que se repete em qualquer sistema sério

Este blueprint vem da engenharia real de um sistema que rodou em produção por 8 anos: a infraestrutura de borda (edge / load balancing) da Atlassian. Cada passo abaixo é uma decisão de arquitetura que se repete em qualquer sistema sério, seja SaaS, CRM, agente de IA ou edge.

A ideia central que amarra tudo: criar a oportunidade de centralizar lógica e resolver preocupações cedo na cadeia de requisições. Você expõe entradas simples pro usuário, valida, e transforma isso em recursos complexos e válidos automaticamente. O usuário manda um pedacinho de JSON; a plataforma monta o mundo inteiro pra ele.

// OS 10 PASSOS · ABRA CADA UM

A arquitetura, peça por peça

01 Comece pelo contrato, não pelo código

Antes de escrever uma linha, defina o que é sucesso. Na entrevista, ele perguntou aos entrevistadores: “olhem 12 meses pra frente; o que eu teria que ter entregue pra vocês dizerem que me contratar foi uma boa decisão?”. A resposta virou o escopo: uma aplicação de load balancers self-service. Esse é o contrato.

No código, o mesmo princípio: ele não começou inventando rotas. Começou pelo Open Service Broker (OSB), uma especificação aberta de API que descreve como provisionar recursos pra uma plataforma (catálogo de serviços e planos, provisioning, binding). Pegou o documento OpenAPI e gerou os handlers a partir dele com a lib connexion (documento OpenAPI vira rotas automaticamente). Depois migrou pra Flask puro, e por fim pra FastAPI.

A lição: contract-first. A forma do sistema nasce do contrato (o que ele promete), não do framework da moda. O framework é trocável (connexion, Flask, FastAPI); o contrato permanece. Escolha um padrão aberto quando existir um, em vez de inventar o seu.
02 O Broker self-service: API + fila + worker + banco

O coração operacional é um broker que provisiona recursos sob demanda, de forma assíncrona. O desenho:

  • App web (FastAPI) recebe a requisição do cliente: “provisione um load balancer pra mim”.
  • O web não faz o trabalho ele mesmo. Ele larga os detalhes da tarefa numa fila (SQS).
  • Um worker consome a fila e executa o provisionamento de verdade: criar registros DNS, criar uma distribuição CloudFront, fazer chamadas de API. Tudo assíncrono.
  • O worker grava o resultado num banco (DynamoDB).
  • O cliente fica fazendo polling: “já ficou pronto? já ficou pronto?”. Quando o worker termina e escreve o status, o web responde “pronto”, ou “deu erro”.

Por que separar web de worker com uma fila no meio? Porque provisionamento é lento e pode falhar. Desacoplar a requisição rápida (HTTP) do trabalho pesado (minutos de chamadas a cloud) dá resiliência: se o worker cai, a tarefa continua na fila; o web nunca trava esperando. Esse é o padrão request › enqueue › async worker › status polling, e ele vale pra qualquer operação cara (geração de imagem, disparo em massa, deploy, cobrança).

A lição: desacople o lento do rápido. Uma fila e um worker no meio transformam uma operação cara e falhável em algo resiliente, sem nunca travar a requisição do usuário.
03 Control plane dinâmico: separe a lógica de configuração da entrada do usuário

Aqui entra a peça mais inteligente. Eles queriam trocar load balancers enterprise (com custo de licença) por um proxy commodity open-source: o Envoy. O Envoy aceita configuração dinâmica via API e recarrega em runtime, então você sobe milhares de proxies parados e empurra config nova quando alguém precisa, sem redeploy.

Pra gerenciar isso ele construiu um management server / control plane (que ele abriu como open source chamado Sovereign, em FastAPI). O control plane recebe duas coisas:

  • Templates: a lógica de configuração por tipo de recurso do Envoy (clusters, routes, listeners).
  • Contexto: os dados dinâmicos, que vêm do banco (via broker) e de outras fontes (um bucket S3 que muda com o tempo).

Quando um proxy pede config, o control plane pega o contexto, injeta nos templates, renderiza a configuração do Envoy e devolve. O contexto muda ao longo do tempo, o template cospe config diferente, o proxy muda de comportamento, sem ninguém logar em servidor nenhum.

A lição de ouro: separe a LÓGICA (templates, do time) da ENTRADA (parâmetros, do usuário). O desenvolvedor manda parâmetros simples; você valida; os parâmetros validados entram como contexto no template; o template gera o recurso complexo e válido. O usuário nunca toca na complexidade. É assim que se constrói abstração de verdade.
04 Infraestrutura como código para o que é de longo prazo

Os proxies não nascem do nada. Eles são provisionados por um template de CloudFormation (infraestrutura como código na AWS). O que entra nesse template, em blocos previsíveis e reutilizáveis: VPC, subnet, internet gateway, security group, key pair, IAM role, auto scaling group, AMI, instâncias EC2, NLB (proxy de camada 4), ACM (certificados) e alguns registros Route 53. Parâmetros são passados em runtime: segredos e chaves entram aí, não ficam no template.

Com esses blocos básicos, eles criaram ~2.000 proxies em ~13 regiões. É infraestrutura long-lived (pré-provisionada, fica de pé o tempo todo), descrita em código, reproduzível e versionada.

A lição: o que é longo-prazo e crítico vira código declarativo, não clique no console. Você ganha reprodutibilidade, multi-região quase de graça, e um histórico auditável de mudanças. Blocos simples de AWS, combinados, viram uma frota inteira.
05 Imagens imutáveis: build once, run everywhere

A AMI (imagem da máquina) que a CloudFormation referencia não é montada na hora; é construída antes num pipeline próprio com HashiCorp Packer + SaltStack (gerenciamento de configuração, primo de Ansible/Puppet/Chef). O fluxo: Packer sobe uma EC2 numa conta de dev, joga a config do SaltStack nela, roda o provisionamento (instala pacotes, põe arquivos, sobe serviços, em ordem e de forma declarativa), e então tira um snapshot e transforma em AMI.

O que vai dentro da imagem (cada um é um “state” do SaltStack): instalar e configurar Envoy, agente de observabilidade (logs, traces, métricas), segurança e hardening, network tuning, containers, tracing, e os sidecars. A AMI sai pronta; a CloudFormation provisiona EC2s a partir dela; tudo já sobe rodando.

A lição: imagem imutável. Você constrói uma vez, testa uma vez, e replica idêntico. Nada de configurar máquina viva à mão. A imutabilidade mata a “deriva de configuração” (cada servidor virando um floco de neve diferente) e torna o deploy previsível.
06 Centralize as preocupações transversais na borda

Esta é a tese que justifica a plataforma inteira. Pense numa requisição do cliente que passa pelo NLB, chega ao proxy, e segue pro backend. Antes de chegar no backend existe um monte de “preocupação transversal”: autenticação, autorização, proteção contra DDoS, rate limiting, access logs.

A pergunta: você resolve isso uma vez na borda, ou obriga mil times de backend a resolverem cada um por si? Resolver na borda economiza tempo, dinheiro e entrega features mais rápido pra todo mundo. Obrigar mil times a reimplementar auth e rate limiting seria um desperdício colossal e ainda atrasaria o produto.

Como cada preocupação foi resolvida ali na frente:

  • DDoS: pelo CloudFront.
  • Access logs: nativamente no proxy, via network filters do Envoy (no HTTP Connection Manager). Tudo configurado de forma dinâmica pelos templates.
  • Autenticação: por um sidecar (mais sobre isso no passo 07).
A lição: mova as preocupações comuns o mais cedo possível na cadeia de requisições. Um ponto central bem feito vale mais que mil implementações meia-boca espalhadas. Vale pra auth, segurança, observabilidade, billing, qualquer coisa que todo serviço precisa.
07 Extensibilidade via sidecar

Nem tudo cabe nativo no proxy. Para preocupações mais complexas, eles usaram o modelo sidecar: o Envoy “conversa pro lado” com serviços locais (containers) que rodam na mesma máquina do proxy. Cada sidecar tem sua própria lógica, separada do proxy, e também recebe configuração dinâmica pela rede localmente.

Times diferentes contribuíram sidecars: o de autenticação foi escrito por ele (em Rust); autorização e rate limiting, por outros times. Esses sidecars eram baixados e configurados na AMI pelo próprio fluxo de provisionamento de imagem (passo 05). Resultado: um proxy programável, extensível por vários times sem tocar no core, cada peça evoluindo no seu ritmo.

A lição: arquitetura de plugins. Um núcleo estável (o proxy) + extensões isoladas (sidecars) que times distintos podem construir e plugar. Isolamento de responsabilidade sem acoplar todo mundo ao mesmo código.
08 Adoção forçada pela plataforma

Construir a plataforma é metade do trabalho; fazer o resto da empresa usar é a outra. A migração teve duas frentes: trazer os produtos grandes pra plataforma, e migrar todos os microsserviços. A segunda foi mais fácil, porque dava pra forçar pela própria plataforma: eles cortaram o load balancer básico antigo, você não conseguia mais expor seu serviço publicamente por ele. Pra ir pra internet, tinha que passar pela infra de load balancing centralizada e configurar isso explicitamente, o que virou um sinal claro de intenção (“eu quero esse serviço público”). Antes, um serviço podia ficar público por acidente, mal protegido.

Assim, Jira, Confluence, Bitbucket, Status Page e muitos outros entraram atrás da infra de borda. A plataforma era genérica e multi-tenant, mas teve que aguentar os casos especiais dos produtos grandes (levou alguns anos de features pra suportar todos).

A lição: torne o caminho certo o único caminho. Quando a plataforma é o único jeito de fazer algo (e ainda elimina configurações inseguras por acidente), a adoção deixa de depender de boa vontade. Default seguro, intenção explícita.
09 Manutenibilidade: documentar, onboardar, vigiar o churn

O sistema rodou 8 anos, então a parte mais subestimada apareceu: manter. No começo de qualquer serviço você precisa onboardar gente, escrever documentação e treinar, pra que saibam contribuir, debugar e ficar de plantão (saber o que cada mensagem de log significa, que métrica olhar quando algo quebra, como resolver os problemas esperados). E precisa antecipar os modos de falha: e se a AWS cair e o banco ficar inacessível? E se o SQS parar e nenhum provisionamento rodar? E se o proxy receber uma config válida porém destrutiva, que mata o tráfego, como você percebe?

Com o tempo, gente entra e sai, traz opiniões novas, mexe no código. Surge o conceito de churn: a área do código que mais muda é previsível, e churn é um cheiro. É um sinal de que aquela parte vai continuar crescendo em tamanho e complexidade, e algo precisa ser feito antes de virar bagunça. O acoplamento se infiltra devagar: você muda uma coisa num canto e quebra outra, e tem que desembaraçar. Construir é fácil; mudar ao longo do tempo, e continuar conseguindo mudar, é o difícil.

A lição: projete pra mudança. Documente e onboarde desde o dia um, mapeie os modos de falha, e fique de olho no churn pra atacar o acoplamento cedo, enquanto ele ainda é barato de desfazer.
10 O lado humano: diplomacia, comunicação e mentoria

A última camada não está no quadro branco, mas é o que sustenta as outras nove. Em 8 anos, o que ele mais desenvolveu foram habilidades de diplomacia, resolução de conflito, persuasão, ensino e mentoria. Personalidades diferentes geram atrito inevitável; o que dá pra fazer é ter autoconsciência, entender a outra pessoa, antecipar o conflito e agir pra a relação funcionar. O feedback recorrente dos colegas foi que ele estava sempre disponível pra ajudar e conseguia destrinchar temas difíceis em algo compreensível, construindo o modelo mental do sistema na cabeça dos outros.

A lição: a comunicação é parte da arquitetura. Um sistema que ninguém entende, ninguém mantém. Saber transformar o complexo em simples, treinar o time e antecipar o atrito humano é o que faz a engenharia durar. Esse é o fosso real, não o framework.

// OS PRINCÍPIOS EM UMA LINHA

Dez decisões, dez frases

“Centralize a lógica e resolva as preocupações cedo na cadeia de requisições.”
01 · Contract-first: a forma nasce do contrato, não do framework.
02 · Desacople o lento do rápido com uma fila e um worker.
03 · Separe a lógica (templates) da entrada (parâmetros validados).
04 · O que é longo-prazo e crítico vira código declarativo.
05 · Imagem imutável: build once, run identical.
06 · Centralize a preocupação transversal cedo, na borda.
07 · Núcleo estável + extensões isoladas (sidecars/plugins).
08 · Torne o caminho certo o único caminho (default seguro).
09 · Projete pra mudança: documente, onboarde, vigie o churn.
10 · Comunicação é arquitetura: o que ninguém entende, ninguém mantém.

Use como base toda vez que for desenhar ou revisar um sistema. Entradas simples pro usuário, complexidade resolvida por dentro, e lógica centralizada cedo: é isso que faz uma plataforma durar.

// Fonte: I was laid off by Atlassian (Vasilios Syrakis) · destilado por Naia · ecossistema Avalanche