Engenheiro Mobile Sênior · iOS, macOS e visionOS nativos · Flutter e as APIs por trás

Maykon Meneghel

Eu entrego o app Apple nativo e a API com que ele conversa.

A maioria dos currículos conta o que alguém sabe fazer. Este aqui deixa você experimentar. Embaixo de tudo isto existe uma coisa só: uma leitura. Eu construí o instrumento que produz uma — firmware, placa, encapsulamento, enterrado num campo — e passei os sete anos seguintes em tudo o que acontece com um número depois disso. Cada capítulo abaixo é um mini-jogo que funciona.

01 · THREAD iOS e Flutter · 2019 → hoje

O frame tem dezesseis milissegundos

Toda discussão de concorrência num time mobile é, no fundo, sobre um número só. Uma tela deve um frame a cada 16,7 ms, e tudo — async/await, actors, isolates, cancelamento — é sobre o que você pode fazer dentro dele. Abaixo está a mesma lista carregada de três jeitos, com o gráfico de frames que um profiler mostraria.

instruments · frame timing

Uma tela deve um frame a cada 16,7 ms. Esta está carregando vinte e quatro linhas, e a única coisa que muda entre os três botões é onde o decode acontece. Olhe o gráfico de frames, não a lista.

Onde o trabalho roda
iPhone · 60 Hz
Tempo dos frames orçamento de 16,7 ms

no orçamento perdido

Pior frame
Frames perdidos
Travamento
Desperdiçado após sair

Um frame que dura quase trezentos milissegundos. A lista não engasga — ela para, e o sistema operacional começa a considerar se o seu app ainda está vivo. Todo engenheiro mobile já subiu isso uma vez.

Swift
 
Flutter
 

O que você acabou de aprender → O botão do meio é o capítulo inteiro. await suspende uma função, não move ela — a continuação retoma no main actor e o trabalho caro ainda cai dentro de um frame. Código assíncrono que nunca sai da main thread é o bug de performance mais comum em mobile, e é invisível até alguém abrir um profiler.

Swift Concurrencyasync/awaitactors@MainActorCombineIsolatescompute()InstrumentsCancelamento de Task60 fps

Ato um

A tela

Uma leitura não vale nada até alguém vê-la, e um celular dá 16,7 milissegundos para mostrá-la. Sete anos entregando app, nativo e cross-platform — e antes deles três anos um nível abaixo, em firmware, placas e peças usinadas, que a Apple Developer Academy transformou nisto: a mesma engenharia, movida para cima na pilha. Este ato são os últimos centímetros desse trajeto — chegar no tempo certo, continuar legível em condições que ninguém projetou, e alcançar só a pessoa certa.

02 · VIDRO Swift e Flutter · 2019 → hoje

O card que sobrevive ao mundo real

Qualquer um constrói o card do layout. O trabalho é construir o que continua legível quando a pessoa que segura o celular colocou a fonte no maior tamanho de acessibilidade, está em tela dividida, num idioma cujas palavras são mais longas, lendo da direita para a esquerda, numa conexão que nunca entregou a imagem. O designer te entrega um estado. Você entrega seis.

PositionRow.swift / position_row.dart

Um card, dois builds. À esquerda o card como ele sai do layout: uma linha só, cada texto numa linha, uma altura em pontos. À direita o mesmo card construído para sobreviver. Ligue as condições e veja qual continua legível — o tamanho de fonte que a pessoa realmente escolheu, uma tela dividida estreita, uma tradução mais longa, um idioma da direita para a esquerda, uma imagem que nunca chegou, um erro sem lugar para aparecer.

Largura disponível
Condições
Estado da tela
Feito pelo layout
BTC-USD Long · 20 lots +1,240.50
    Feito para sobreviver
    BTC-USD Long · 20 lots +1,240.50
      SwiftUI
      // The whole fix is three decisions.
      HStack(alignment: .firstTextBaseline, spacing: 12) {
        if let image { Thumbnail(image) }        // no image, no box
        VStack(alignment: .leading, spacing: 2) {
          Text(position.symbol)
            .font(.headline)
            .lineLimit(nil)                      // let it wrap
          if let error { Text(error).foregroundStyle(.red) }
          else { Text(position.summary).font(.subheadline) }
        }
        Spacer(minLength: 12)
        Text(position.pnl, format: .currency(code: code))
          .monospacedDigit()
      }
      .padding(.horizontal, 16).padding(.vertical, 12)
      .frame(minHeight: 44)                      // grows, never clips
      .dynamicTypeSize(...DynamicTypeSize.accessibility5)
      .accessibilityElement(children: .combine)
      .accessibilityLabel(position.spokenLabel)
      Flutter
      // Same three decisions, same order.
      Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (image != null) Thumbnail(image!),
          const SizedBox(width: 12),
          Expanded(                              // min-width: 0, in Flutter
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(p.symbol, style: t.titleMedium, softWrap: true),
                error != null
                  ? Text(error!, style: t.bodySmall!.copyWith(color: cs.error))
                  : Text(p.summary, style: t.bodySmall),
              ],
            ),
          ),
          const SizedBox(width: 12),
          Text(p.pnl, style: t.titleMedium),
        ],
      )
      // Directionality mirrors the row; Semantics gives it one spoken label.

      O que você acabou de aprender → O layout desenhado no comp sobrevive a uma das sete condições aqui embaixo — justamente aquela para a qual ele foi desenhado. A diferença não é gosto, é qual pergunta o layout faz: não "a fonte está grande?" e sim "isso cabe?". Faça a segunda pergunta e uma tradução mais longa deixa de virar um chamado de bug.

      SwiftUIUIKitFlutterDynamic TypeVoiceOverLocalizaçãoRTLLayout adaptativoAcessibilidadeDesign systems

      03 · PORTA Tradx · 2022 → hoje

      O login é por onde arrombam um app

      Todo o resto num app mobile falha de forma visível. Isso falha em silêncio: o login funciona, a pessoa entra, e o fluxo ficou aberto o tempo inteiro. Eu refiz esse pedaço na Tradx depois de ler a nossa própria implementação com atenção — são as cinquenta linhas que eu perguntaria em qualquer entrevista sênior.

      oauth · tratamento do redirect

      Autenticar alguém pelo navegador e devolver o resultado para o app são as cinquenta linhas mais sensíveis de um código mobile. Comece pela versão que todo tutorial mostra e feche uma chave por vez. A ordem importa mais do que você gostaria.

      O redirect
      O que volta
      Proteções
      1. O app abre o navegador ASWebAuthenticationSession, não uma web view — o cookie de sessão precisa ser o de verdade
      2. A pessoa faz login e o servidor de autorização redireciona de volta
      3. O aparelho roteia o redirect para qualquer app que reivindique aquele endereço
      4. O app lê o callback da URL, que vai para logs e histórico
      5. O app troca o código por uma sessão, sobre TLS, a partir do próprio app
      6. Alguém apresenta de novo o mesmo valor, uma segunda vez
      7. A sessão vai para o keychain e a pessoa entrou
      O redirect chega a
      Ataques que passam
      • Sequestro de esquema qualquer outro app do aparelho pode registrar tradx:// e receber o redirect no seu lugar
      • Token no log um access token na query string é gravado em logs do sistema, histórico do navegador e referrer
      • Replay do código um código aceito duas vezes é um access token com passos a mais
      • Interceptação do código sem PKCE a troca não prova nada sobre quem iniciou o fluxo, então quem tiver o código gasta ele
      • Callback forjado sem um state impossível de adivinhar o app aceita um login que a pessoa nunca iniciou

      Comece pela versão do tutorial e feche uma chave por vez. Veja até onde o redirect chega.

      O que você acabou de aprender → Trocar o token por um código de uso único é a primeira correção que todo mundo tenta, e sozinha ela abre dois buracos para fechar um. Um código precisa de PKCE para que só o app que iniciou o fluxo o gaste, e de uso único para não ser gasto duas vezes. Meia migração de segurança é pior que nenhuma, porque parece terminada.

      OAuth 2.0PKCEUniversal LinksASWebAuthenticationSessionKeychainApp LinksDeep linkingModelagem de ameaças

      Ato dois

      Com o que o app conversa

      Volte a partir da tela e você encontra o trajeto que o número percorreu para chegar até ela. Ele precisa chegar enquanto ainda é verdade, ser encontrado entre centenas de milhares de irmãos, aguentar todo mundo perguntando ao mesmo tempo, e enfim valer uma decisão. Quatro capítulos — e no último, as quatro decisões são minhas.

      04 · PULSO Tradx · 2022 → hoje

      O cliente não devia precisar perguntar

      Quase tudo que um app mostra é a resposta de uma pergunta que ele fez. Um preço ao vivo não é: quando a resposta chega, a pergunta já mudou, e perguntar de novo gasta uma requisição inteira para ouvir, quase sempre, que nada aconteceu. Este capítulo é a diferença entre um endpoint que responde e um canal que te avisa.

      tradx · feed de preços

      Um minuto de um feed de preços, reproduzido. Escolha como o cliente fica sabendo — perguntar num cronômetro, ou ser avisado — e então acompanhe os dois números: o que o mercado está fazendo, e o que o leitor está de fato olhando.

      Transporte
      O mercado
      Na tela
      0.0s
      Requisições
      Bytes por minuto
      Ticks vistos
      Desatualizada

      Uma conexão, {bytes} no minuto inteiro, e todos os {emitted} ticks chegaram. A tela mostrou um preço já superado em {behind} do tempo — o voo em si, e nada além disso.

      O que você acabou de aprender → Perguntar uma vez por segundo custou oito vezes mais bytes do que manter um socket aberto — e ainda assim perdeu um quarto dos ticks. Frequência não é atualidade: o único jeito de parar de chegar atrasado é parar de perguntar.

      Node.jsNestJSWebSocketsAPIs RESTArquitetura orientada a eventosDesign de API

      05 · SERVIÇO Backend · 2018 → hoje

      Alguém precisa lembrar de tudo isso

      Uma leitura que ninguém guardou é uma leitura que não aconteceu. Atrás de cada dispositivo e de cada cliente existe uma API e um banco, e a diferença entre um produto rápido e um lento costuma ser uma única decisão tomada aqui. A tabela abaixo tem duzentas e quarenta mil leituras de sensor — do tipo que a sonda da outra página passou dois anos produzindo.

      psql · meneghel_db

      Uma tabela de leituras de sensor, 240.000 linhas. Escolha uma consulta, decida quais colunas ganham índice, e rode. A faixa abaixo é a tabela; repare em quanto dela o banco precisa tocar.

      Consulta
      SELECT * FROM readings WHERE reading_id = 128374
      CREATE INDEX ON

      índice · árvore B

      18 pages

      tabela · readings · 240.000 linhas

      Linhas lidas
      Tempo da consulta
      vs varredura completa
      Custo de escrita

      O que você acabou de aprender → Sem índice, o banco lê todas as linhas para te responder. Com um, ele salta direto ao ponto. Mesma query, mesmos dados, mesmo servidor — mil vezes mais rápido.

      Node.jsExpressRestifyMongoDBPostgreSQLREST

      06 · ENXAME Backend · 2018 → hoje

      Uma máquina nunca é suficiente

      Um leitor é uma query; dez mil ao mesmo tempo é uma arquitetura. Tráfego não chega educadamente — ele chega todo de uma vez, às 3 da manhã, no dia do lançamento. Containers e Kubernetes são como você responde a isso sem acordar.

      kubectl · production

      O tráfego deste serviço dispara a cada poucos segundos, como num dia de lançamento. Adicione réplicas e a latência cai; adicione demais e você paga por máquina ociosa. Depois entregue ao autoscaler e veja onde ele ainda perde.

      Entrada Réplicas × 60 rps

      prontos 0 subindo 0

      Você está escalando na mão. O pico chega estando você pronto ou não.

      Entrada 0
      Saturação 0%
      Latência p99 0 ms
      Requisições perdidas 0
      Custo $0

      O que você acabou de aprender → Você não deixou o código mais rápido — você fez mais cópias dele. Escala horizontal troca dinheiro por latência, e um autoscaler faz essa troca por você, sozinho.

      DockerKubernetesHPALoad balancingCI/CD

      07 · FLUXO Tradx · 2022 → hoje

      E então eu construí a ferramenta

      A Tradx é o meu sandbox — o lugar onde eu tomo todas as decisões e convivo com todas elas. Um cliente de trading para desktop escrito em Flutter, onde uma estratégia é um grafo que você liga em vez de um código que você escreve, publicado na Mac App Store e na Microsoft Store, com cerca de quinze mil downloads somando as duas. Somos dois construindo: eu e o Luiz Veloso, por pull request, com review que nenhum dos dois pula.

      tradx · grafo de estratégia

      É isso que o Tradx faz, em miniatura. Você não escreve o laço — você liga a lógica, e o motor roda ela sobre os candles. Mexa nos parâmetros e veja o grafo e as operações mudarem juntos.

      O editor de estratégias do Tradx: um gráfico de candles de PETR4 acima de um grafo de nós ligando uma média móvel e um RSI a duas entradas a mercado.
      Tradx · o editor de estratégias. Sete nós, sete conexões, e um backtest rodando em PETR4 no gráfico de quinze minutos.

      Duas pessoas, pull requests, e review que nenhum dos dois pula.

      Dados de mercado Indicador RSI Cruzamento p/ cima Cruzamento p/ baixo Entrada Saída
      Operações 0
      Retorno 0%
      Acerto 0%

      Ajuste até o número ficar bonito. Essa é a parte fácil, e é o que todo print de backtest na internet está te mostrando.

      O que você acabou de aprender → Um backtest é uma hipótese, não um resultado. Qualquer um ajusta uma curva até ela ficar bonita nos dados que já tem; o ofício inteiro é saber quanto aquele número vale nos dados que ele não tem.

      Node.jsNestJSFlutterMongoDBRedis + BullMQMotor de backtestPaper trading

      Ato três

      E os modelos por baixo

      Tudo até aqui move uma leitura que já existe. Este inventa a próxima — e é onde as duas metades deste site se revelam uma só. Eu treinei o modelo com dados de mercado; ele roda aqui sobre uma sonda de solo que eu enterrei anos antes, sem mudar uma linha, porque uma série temporal não sabe o que ela mede.

      08 · MENTE StockGAN · 2021

      Ensine a máquina a adivinhar o que vem depois

      Em 2021 eu construí do zero uma rede adversária generativa para séries temporais — o trabalho em que a minha pós em IA e o mestrado em Bioengenharia deixam de ser linhas num diploma — duas redes, uma tentando inventar a próxima leitura e outra tentando pegá-la mentindo. Eu treinei em dados financeiros. Ela roda aqui numa sonda de solo que eu projetei e enterrei anos antes, sem mudar nada, porque uma série temporal não sabe o que ela mede.

      gan_model.py — train_step()

      Em 2021 eu escrevi uma GAN que prevê o próximo valor de uma série temporal — gerador, discriminador e loop de treino do zero. Eu treinei em trinta anos de barras diárias, porque era ali que havia histórico limpo de graça, mas a rede lê log-retornos e não faz ideia do que os números medem. Então aqui ela está rodando numa sonda de solo que eu construí anos antes de tudo isso. A parte que vale mostrar é esta: o discriminador nunca julga uma leitura prevista sozinha. A leitura é colada nas nove reais que vieram antes, e a rede precisa dizer se a janela inteira saiu do sensor. É esse o jogo. Você é o discriminador.

      StockGAN · LSTM(128) · janela de 10 · treinada em 30 anos de barras diárias, rodando aqui no soil-1

      Uma destas duas janelas termina com uma leitura que a sonda realmente fez. A outra termina com uma que o gerador inventou. Qual é qual?

      Rodadas 0
      Você
      O discriminador
      Enganou o crítico

      Escolha uma. Nove leituras reais, e uma décima que é a sonda ou o meu gerador.

      1 − λ · MSE λ · critic o que eu subi · 0.60
      Perto da verdade
      Anda como o sensor
      O que existe de fato no arquivo gerador LSTM(128, stateful) → Dropout(0.3) → Dense(n_features) discriminador LSTM(128, stateful) → Dropout(0.1) → Dense(1, sigmoid)

      RMSprop com decaimento polinomial de 2.5e-4 até 1e-4 ao longo de mil passos. Entropia cruzada com label smoothing em 0.2, para que o discriminador nunca tenha permissão de ter certeza absoluta de nada. Alvo real e alvo gerado multiplicados por ruído com σ = 0.25 durante o treino, para que ele não vença percebendo quais números são limpos demais. Doze indicadores — MACD, EMA, RSI, Bollinger, ROC, volatilidade — reduzidos por PCA e XGBoost antes de a rede ver qualquer coisa; numa sonda de solo esses mesmos doze viram médias móveis e taxa de variação da umidade, e é justamente esse o ponto: a arquitetura mudou de domínio e o pipeline de features quase não piscou. As funções de perda desta página são portes das reais, constantes incluídas; o gerador daqui é um substituto que reproduz o dilema sem carregar 128 unidades LSTM para dentro do seu navegador.

      O que você acabou de aprender → Dois modelos, uma função de perda e um botão entre eles. Cobre do previsor que ele fique perto e ele responde com a média de tudo, que é segura e inútil. Cobre que ele seja crível e ele responde com algo que anda como o sensor e não sabe de nada. Todo modelo que eu entrego é essa troca feita de propósito, escrita e medida.

      TensorFlow / KerasGANsLSTMSéries temporaisSeleção de features com PCA e XGBoost

      Ato quatro

      E então saiu da tela

      E agora a medida é o objeto. No Eldorado, em macOS e visionOS, uma coisa tridimensional deixa de ser algo que um engenheiro desenhou e passa a ser algo que uma câmera mediu — o mesmo movimento que eu fiz em 2019, repetido, agora sobre o mundo.

      09 · CAMPO Eldorado · 2022 → hoje

      E agora o objeto é feito de luz

      O capítulo anterior inventou o próximo número de uma série. Este para de tratar o mundo como algo que alguém desenha. Uma cena deixa de ser uma superfície que alguém modelou e vira uma nuvem de gaussianas orientadas, ajustadas por gradiente descendente até que renderizações delas batam com as fotografias — o que significa que ninguém a desenha, e não sobra malha nenhuma para converter. Reconstruções de verdade começam com uma câmera andando por uma sala. A demonstração abaixo deliberadamente não: ela usa uma peça que eu mesmo projetei e imprimi, porque o único jeito de ver o que o método muda é assistir ao mesmo objeto construído dos dois jeitos.

      gaussian splatting · visualizador

      Um objeto, construído duas vezes. De um lado da chave é a malha pela qual a peça foi impressa. Do outro é um campo de gaussianas sobre essa mesma malha — espalhadas aqui em vez de ajustadas, para os dois ficarem lado a lado e a diferença ser o método e mais nada.

      ↔ arraste para girar

      carregando a malha…

      Primitivas
      Feitas à mão

      997 triângulos, cada um colocado por alguém no SolidWorks em 2017.

      O que você acabou de aprender → Uma malha diz onde estão as superfícies, e um engenheiro desenhou cada uma. Um campo de splats diz onde está a luz, e ninguém desenhou nada disso — foi ajustado até a renderização parar de discordar da fotografia.

      Gaussian Splatting3DGSvisionOSmacOSPyTorchCUDAFotogrametriaCampos de radiância

      10 · TRAJETÓRIA

      As provas

      Nove capítulos de demonstração. Este aqui é só evidência. Arraste pelos anos e veja o que estava rodando ao mesmo tempo — porque a manchete honesta desta linha do tempo não é nenhum emprego específico, é o quão raramente houve só um.

      timeline · 2012 → 2026
      2026
      ← arraste o ano →

      Formação

      Eng. de Controle e Automação PUC-PR
      Mestrado em Bioengenharia PUC-PR
      Pós-graduação lato sensu, Desenvolvimento iOS Apple Developer Academy
      Especialização em Inteligência Artificial Aplicada PUC-PR

      Pesquisa

      Estagiário, Laboratório de Automação e Sistemas PUC-PR · LAS
      Engenheiro de Software — pesquisa aplicada, IA e saúde embarcada Fundação Araucária

      Indústria

      Desenvolvedor de Software, autônomo Self-employed
      Trainee · Apple Residency Eldorado · Apple
      Desenvolvedor Júnior · Projeto Apple Eldorado · Apple
      Tech Lead · Apple Internship Eldorado · Apple
      Desenvolvedor Full Stack · Projeto Apple Eldorado · Apple
      Desenvolvedor Sênior · Projeto Apple Eldorado · Apple
      Technology Advisor · Projeto Renault GHEL

      Empreendimentos

      Conselheiro Administrativo — a holding da família RJ Meneghel Holding
      COO e Cofundador Tradx

      De trainee a sênior em quatro anos

      Entrei no projeto Apple em 2022 como trainee e sigo no mesmo produto, hoje como sênior. Ninguém é promovido por calendário: cada degrau veio de pegar algo que ninguém queria — o processo de release, a suíte instável, a tela que todo mundo reescreveu duas vezes — e transformar aquilo num problema fácil para os outros. Arraste o ano e olhe a faixa de indústria: as quatro barras em sequência são o mesmo produto e o mesmo time, vistos de quatro níveis de responsabilidade diferentes.

      Seis empresas

      Fundadas ou cofundadas. Algumas cresceram, outras não — que é exatamente o motivo de fundar seis.

      • Tradx Cofundador · fintech
      • Agrom.IO Fundador · agritech
      • Dommuz Cofundador · casa inteligente
      • Psiu Cofundador · proptech
      • Hubli Cofundador · edtech
      • PreditChart Cofundador · fintech

      Publicado e premiado

      Seis trabalhos acadêmicos, três deles com revisão por pares, e nenhum sobre mobile — e é justamente esse o ponto. Foi ali que eu aprendi a errar em público: a descrever um método com precisão suficiente para outra pessoa atacá-lo, receber o parecer e mudar a afirmação. Esse hábito vale mais num code review do que qualquer um dos resultados.

      • Instrumento para Medição de Fatores e/ou Elementos Naturais do Solo 2016 · Control & Automation Engineering, PUC-PR
      • A Tool to Select FES Parameters for chronic SCI 2019 · 41st Annual International Conference of the IEEE EMBS · ler o artigo ↗ · doi:10.1109/EMBC.2019.8857421 · código ↗
      • Indoors Wi-Fi Fall Detector Buckle for the Elderly 2019 · Advanced Materials Proceedings, 4(1), 40–45 · ler o artigo ↗ · doi:10.5185/amp.2019.1450 · código ↗
      • Aplicação, in silico, de estímulos elétricos em modelo neuromuscular compatível com lesão medular crônica 2019 · M.Sc. dissertation in Bioengineering, PUC-PR · ler o artigo ↗ · código ↗
      • Modelagem matemática do sistema de manutenção do equilíbrio por técnicas de identificação de sistemas 2018 · V Congresso Brasileiro de Eletromiografia e Cinesiologia · X Simpósio de Engenharia Biomédica · ler o artigo ↗
      • Previsão de Séries Financeiras com Redes Generativas Adversárias 2020 · Applied AI specialization, PUC-PR

      Na imprensa

      • Hubli, criado na Apple Developer Academy — a Apple me nomeia entre os cinco criadores Apple Newsroom · 2021 · ler a matéria ↗
      • Neon Wave, jogo de iOS que saiu no MacMagazine MacMagazine · 2020 · ler a matéria ↗

      Eu construo o app, e construo aquilo com que ele conversa. A tela, o estado nela, a API que a preenche, o banco embaixo disso, e o modelo que lê tudo. A maioria das pessoas domina uma dessas. Eu já entreguei todas, e ainda sei qual é a parte difícil.

      Com o que eu trabalho

      Tudo aqui embaixo é creditado por algum capítulo desta página ou está num repositório público. Nada aqui é aspiracional.

      iOS · Swift
      Swift · SwiftUI · UIKit · visionOS · macOS · Swift Concurrency · async/await · actors · Combine · MVVM · Coordinators · Clean Architecture · Dependency injection · SwiftData · Core Data · URLSession · Swift Package Manager · XCTest · XCUITest · Instruments · Xcode · App Store Connect · TestFlight · VoiceOver · Dynamic Type · Localization · Push notifications · Deep linking
      Multiplataforma
      Flutter · Dart · Riverpod · Bloc · Provider · Kotlin · Jetpack Compose · Android · Platform channels · Offline-first · State management · Widget testing
      Publicação e release
      fastlane · Xcode Cloud · GitHub Actions · CI/CD · App Store review · Phased release · Firebase Crashlytics · Crash-free rate · Analytics · Feature flags · Semantic versioning
      Linguagens
      Swift · Dart · Kotlin · Java · TypeScript · JavaScript · Python · C · C++ · MATLAB · SQL
      Backend e APIs
      Node.js · NestJS · Express · Java · REST APIs · WebSockets · Microservices · OAuth 2.0 · JWT · API versioning · Distributed systems · System design · Event-driven architecture · API design
      Dados
      MongoDB · PostgreSQL · Redis · BullMQ · Database design · Indexing and query planning · Time series · Data pipelines
      Cloud e DevOps
      AWS · Amazon S3 · CloudFront · Route 53 · AWS IoT Core · IAM · EC2 · Docker · Kubernetes · Terraform · Infrastructure as Code · GitHub Actions · CI/CD · OIDC · Observability · Scalability · Linux
      Web
      Astro · HTML · CSS · Accessibility · Design systems · Responsive layout
      IA e 3D
      Machine learning · PyTorch · TensorFlow · Keras · GANs · LSTM · Deep learning · Feature selection · PCA · XGBoost · Gaussian Splatting · 3DGS · CUDA · Photogrammetry · Computer vision
      Embarcados e hardware
      Embedded C · ESP32 · PIC18F4550 · ATmega · PWM · ADC · MQTT · IoT · PCB design · EAGLE · Altium · SolidWorks · CAD · 3D printing · Design for manufacturing
      Jeito de trabalhar
      Git · Code review · Unit testing · Technical leadership · Mentoring · Product engineering · Backtesting · Paper trading

      Fale comigo

      Se alguma coisa aqui tem a cara de um problema que você tem, eu quero ouvir. E-mail ou LinkedIn, o que preferir — o CV é um PDF de duas páginas e o código está no GitHub.