Outcome-Driven Systems Architect

TypeScript Angular NestJS PostgreSQL C++ IA / MCP

Lucas Hiago constrói sistemas como quem projeta estruturas para atravessar o tempo. Enxerga software como infraestrutura estratégica, não código passageiro: cada decisão técnica carrega consequências que só se revelam quando o produto cresce, a equipe evolui ou o mercado exige mais do que a base foi preparada para suportar. Seu foco é segurança, desempenho, redução de débito técnico e, sobretudo, escalabilidade sustentável. Atua justamente quando os sistemas começam a sentir o peso do próprio crescimento — reorganizando arquitetura, fortalecendo camadas críticas e eliminando fragilidades invisíveis que comprometem o futuro do negócio.

Ao longo de mais de uma década construindo e reestruturando plataformas de e-commerce, sistemas financeiros, soluções com IA, blockchain e experiências interativas, desenvolveu uma disciplina orientada à eficiência estrutural. Bancos bem modelados, APIs previsíveis, controle de acesso consistente, performance mensurável e infraestrutura pronta para expansão real não são diferenciais estéticos — são fundamentos inegociáveis. Entende que dados, estado, transações e inferência precisam coexistir em equilíbrio, e que escalar não é só suportar mais usuários: é manter clareza, estabilidade e segurança enquanto o negócio amadurece. Para ele, software não é espetáculo nem promessa vazia — é engenharia aplicada ao mundo real, onde decisões conscientes sustentam crescimento e decisões frágeis cobram juros silenciosos no futuro.

Marcos de desenvolvimento
2013
2015
  • Freelancer na Workana — primeiros contratos e entregas reais.
  • Landing pages, sites institucionais e WordPress para agências de marketing.
  • Web scraping em PHP para coleta e automação de dados.
  • Primeira escola de escopo, prazo e bug em produção.
2016
2020
  • Consolidação como front-end e fullstack passando por Romana Informática, BITS&GAMES, 2ck e Open Digital.
  • Romana — suporte, infraestrutura e e-commerce em PHP; base sólida de diagnóstico e rede.
  • BITS&GAMES — WordPress e lojas MercadoShops, com forte personalização de temas.
  • 2ck — e-commerce profissional (Rakuten, Tray, Jet); ritmo intenso e múltiplos clientes.
  • Open Digital — virada de WordPress para Angular; Real Estate e suporte a .NET/CSHTML (MRV).
  • 2020, Alpes.One / Carbel — refatoração de um main.js de 26 mil linhas; webpack reestruturado e modularização em centenas de arquivos.
2021
2024
  • JET — Frontend Developer (Angular); produto Elegance (Angular + API Node) e template base do produto.
  • Loja Virtuol — quatro temas comerciais; liderança no upgrade Angular 9 → 14 e Node → 18 (vulnerabilidades corrigidas).
  • Serviços Profissionais com foco em .NET, em ambientes corporativos e stacks heterogêneas.
  • SQUADEVOPS — projetos ponta a ponta (Angular, Svelte, Nest, WebRTC, TypeScript), foco em modularização e escalabilidade.
  • 2024 — virada estratégica: reposicionamento da SQUADEVOPS e início da atuação consultiva.
2025
2026
  • Steply consolidada como CTO as a Service — Fractional CTO e consultoria (Brasil e exterior).
  • Arquiteturas escaláveis, mentoria de times e otimização de infra (custo operacional e previsibilidade).
  • Supero Tecnologia — Senior Software Engineer (2024 – fev/2026): Angular 15+, Azure, integração Zendesk.
  • Fev/2026 — lançamento do livro DE VOLTA aos FUNDAMENTOS: fundamentos, arquitetura sólida e construção consciente.
  • Transição de executor técnico para referência em fundamentos e arquitetura.
Frentes autorais

Além da consultoria, três frentes próprias na fronteira técnica. Engenharia de base, não slide.

Engenharia autoral

Engine de jogo própria — C++

Asteroth: mundo isométrico num planeta esférico real — horizonte curvo e geometria de mundo, não skybox falso. Engine própria desde 2012, com pipeline híbrido CV + IA generativa que converte sprite-sheet ortográfica em mesh 3D fiel à arte em segundos.

C++ECSCV + IA
Repositório público
IA aplicada

Pipelines com MCP, agentes e RAG

Automação de produção via Model Context Protocol (Blender e tooling próprio), agentes orquestrados com LangGraph + pgvector e geração 3D multi-view. IA dentro do produto, com tier por tarefa — não jogada por cima.

MCPLangGraphpgvector
Skills públicas
Processo

Spec-Driven Development harness

Arcabouço que estrutura épico → issue → spec → código, rastreável via GitHub CLI e versionado no Git. Templates, ERD como fonte de verdade e tooling em lote. Arquitetura sem processo vira folclore.

specstoolinggh
Manifesto técnico
Open source · impacto social

Mapa de hospitais com soro antipeçonhento

App open-source que mostra a localização de hospitais com soro para acidentes com animais peçonhentos — cobra, escorpião, aranha. Informação que salva vidas quando cada minuto conta, aberta e acessível a qualquer pessoa.

open sourcemapasaúde
Acessar o app
Deep-dives técnicos

Perguntas difíceis de arquitetura de IA, respondidas como eu respondo numa sala técnica — direto, opinativo, com o trade-off explícito. Não é teoria de slide.

Como você arquitetaria um RAG em produção com múltiplos agentes, controle de custo por token e fallback quando o modelo principal cai? Difícil

Uso OpenRouter (OR) como camada de roteamento, porque é onde fallback e multi-provider ficam triviais.

1. Ingestão (offline). Chunking semântico com metadados (fonte, data, tenant/permissão). Embeddings: escolha um provider e fixe — não troque de modelo de embedding sem reembeddar tudo, vetores ficam incompatíveis. Cada modelo no OR tem tokenizer próprio: use o usage real retornado, não confie num tokenizer único pra todo o catálogo.

2. Retrieval (online). Híbrido (vetorial + BM25) com rerank. O rerank é onde se corta token: só os top-k de verdade entram no prompt. É a maior alavanca de custo — chunk irrelevante é input pago em toda chamada.

3. Orquestração multi-agente. Mapeie papel → modelo e force custo/throughput pelo provider: roteador → gemini-flash ou um :nitro barato com sort: "price"; workers de extração → sonnet/deepseek (custo-benefício); síntese → opus/gpt-4o com sort: "throughput". O OR não tem "subagente com cache compartilhado" da Anthropic — multi-agente aqui é orquestração do seu lado: chamadas paralelas, junção na aplicação.

4. Custo por token. Roteamento por preço (sort: "price"), teto por requisição (max_price), e prompt caching repassado pelo provider — system + docs estáveis no prefixo cacheável, pergunta volátil no fim. Peça usage: { include: true } pra ter custo real e fazer budget por tenant.

5. Fallback (onde o OR brilha). Dois níveis automáticos: entre modelos (models é lista ordenada, cai pro próximo na mesma requisição) e entre provedores do mesmo modelo (allow_fallbacks: true). No Claude direto você coda a cascata na mão e distingue refusal de 529.

Cuidado: ao cair pra outro modelo o cache se perde (é por modelo/provider) e o comportamento muda. Ordene a lista por similaridade de comportamento, não só por preço.

Como funciona o prompt caching da Anthropic, e quando ele de fato economiza? Médio

O que governa tudo: caching é prefix match. A chave vem dos bytes exatos do prompt renderizado até cada breakpoint cache_control. Qualquer byte que muda na posição N invalida tudo depois. A ordem de render é tools → system → messages, então um breakpoint no último bloco de system cacheia tools + system juntos.

Como projetar. Estável fisicamente antes do volátil: system congelado e documentos recuperados no prefixo; pergunta da vez, timestamps e IDs no fim. Num RAG isso é a diferença entre pagar 0,1× ou 1× pelos docs em cada chamada.

Economia real. Leitura ~0,1× o input; escrita 1,25× (TTL 5 min, padrão) ou (1h). Break-even: com 5 min, duas requisições já pagam; com 1h, pelo menos três.

Pegadinhas. Máx 4 breakpoints. O prefixo mínimo cacheável depende do modelo — abaixo dele não cacheia, em silêncio (cache_creation_input_tokens: 0): ~4096 tokens em Opus/Haiku, ~1024–2048 em Sonnet. Invalidadores que eu caço: datetime.now() ou UUID no system, json.dumps sem sort_keys, tools variando por usuário, trocar de modelo no meio. Confiro com usage.cache_read_input_tokens — se vier zero em prefixos idênticos, tem invalidador escondido.

Diante de um problema novo, como você decide entre prompt engineering, RAG e fine-tuning? Médio

Ordem default: prompt engineering → RAG → fine-tuning, escalando só quando o anterior comprovadamente não resolve. Menor custo, menor acoplamento, maior reversibilidade.

  • Prompt engineering — quando o conhecimento já está no modelo e o problema é de formato, tom ou raciocínio. Iteração em minutos. 70% dos casos morrem aqui.
  • RAG — quando o problema é de conhecimento: dados privados, atuais ou grandes demais pro contexto, que mudam com frequência. A fonte da verdade vive fora do modelo: atualizar é reembeddar um documento, não retreinar nada.
  • Fine-tuning — último recurso, e quase nunca pra "ensinar fatos" (RAG faz melhor e versionável). Vale pra comportamento consistente que prompt não estabiliza: formato muito específico em altíssimo volume, estilo, ou comprimir instrução longa no peso. Custo: dataset, pipeline e perda de reversibilidade.

Heurística: "é falta de conhecimento ou de comportamento?" Conhecimento → RAG; comportamento → prompt primeiro. O caso mais comum em produção é RAG + prompt bem-feito, sem fine-tuning nenhum.

Como garantir saída estruturada confiável (ex.: JSON) de um LLM em produção, sem o parser quebrar? Médio / difícil

Regra: não confie em "peça JSON no prompt e dê json.loads". Funciona no happy path e te acorda 3h da manhã quando o modelo abre com "Claro! Aqui está:". Confiabilidade vem de restringir a saída na API, não de pedir educadamente.

Camada 1 — restrição nativa. output_config.format com JSON Schema, ou tool use com strict: true (additionalProperties: false + required), que garante que o tool_use.input valida exato. Pra classificação, tool com enum dos rótulos é mais robusto que pedir rótulo em texto. SDKs dão validação tipada (Pydantic, Zod).

Camada 2 — parsing defensivo. Mesmo com schema, sempre json.loads()/JSON.parse()nunca regex na string serializada. Modelos diferentes escapam Unicode e barras de formas diferentes.

Camada 3 — modos de falha restantes. Se stop_reason é max_tokens o JSON vem truncado; se é refusal pode não bater com o schema. Então: schema estrito + parse defensivo + checagem de stop_reason antes de tratar como válido. Três camadas, porque cada uma cobre um modo de falha diferente.

Diferença entre orquestração multiagente "de verdade" (LangGraph StateGraph) e só encadear chamadas — e quando a complexidade se paga? Difícil

Encadear é pipeline linear: saída de A vira entrada de B, fluxo fixo. StateGraph é máquina de estados: nós que leem/escrevem num estado compartilhado (AgentState, inspecionável em qualquer ponto), com arestas condicionais que decidem o próximo nó em runtime — incluindo ciclos. A diferença é a capacidade de loop, branch e retomada com estado explícito.

No meu lab (agentes-langchain-lab) o grafo é researcher → writer: o researcher é um agente ReAct com a tool search_docs fazendo RAG, e repete pensa→busca→observa até ter evidência — isso é um ciclo, não dá pra expressar limpo numa cadeia. O writer só entra quando o estado tem evidência.

Quando NÃO se paga: fluxo determinístico e linear (extrai → transforma → resume). StateGraph aí é over-engineering; três await são mais legíveis e baratos. Trazer o framework só porque "é multiagente" é o erro mais comum.

Quando SE paga: ciclos com parada decidida em runtime, branching real, estado compartilhado entre nós heterogêneos, ou checkpoint/retomada de execuções longas. Resumindo: encadeie quando o fluxo é fixo; use grafo quando o próprio fluxo é decisão do modelo.

Você cortou ~68% do consumo de tokens num time multi-repo com Claude Code. Como, e por que não degrada a qualidade? Médio / difícil

Insight central: o gargalo de custo em assistência multi-repo não é o que o modelo gera, é o que fica sempre carregado no contexto — regras, comandos, skills, CLAUDE.md — multiplicado por toda interação. Numa tarefa representativa eram 377K tokens; caiu pra 28K (~68% num time de 6).

Estratégia "slim rule + skill sob demanda": separar o que precisa estar sempre presente do que só importa quando a tarefa pede. A regra slim carrega um índice magro — o que existe e quando puxar — e a orientação detalhada vive em skills lidas on-demand. Contexto fixo pequeno; profundidade paga sob demanda.

Por que não degrada: não removi informação, mudei quando ela entra. Tocou o auth, o skill detalhado do auth é carregado integralmente — orientação completa, na hora certa. O que cortei foi carregar a guideline dos 18 serviços pra editar um. É a mesma lógica do prefixo cacheável, levada pra arquitetura de contexto: minimize o fixo, pague o resto sob demanda.

Capa
Verso

Em 2025 escolhi desacelerar para fortalecer o que realmente sustenta qualquer tecnologia: os fundamentos. Este livro não é sobre frameworks, é sobre como pensar. Ele conecta algoritmos, estruturas de dados, patterns e arquitetura a sistemas reais, mostrando Big O aplicado, decisões com trade-offs conscientes e código evoluindo para soluções sustentáveis. Também encara a era da IA com maturidade, defendendo que ela potencializa quem domina a base e fragiliza quem não domina. É um manifesto contra a superficialidade técnica: menos modismo, mais estrutura; menos complexidade desnecessária, mais clareza.

Resultado financeiro nasce de base técnica sólida.

O que trava o crescimento muitas vezes não é marketing — é débito técnico acumulado: arquitetura frágil, patterns mal aplicados, modelagem ruim e código complexo demais. Escalar só com banco e infraestrutura vertical aumenta a fatura sem resolver o problema estrutural. Quando a arquitetura é bem pensada e a carga é distribuída com inteligência, o custo cai, a previsibilidade aumenta e a tecnologia deixa de ser desperdício para virar alavanca real de margem e crescimento.