Concorrência é um daqueles conceitos que parecem simples na teoria, mas quebram sistemas inteiros na prática.
Para deixar isso mais intuitivo, gosto de pensar em uma história simples.
Imagine um prédio com uma sala que tem um quadro de avisos.
Um professor te pede um favor:
“Você pode entrar lá e escrever no quadro que minha aula será às 15h e o local?”
A sala tem várias portas. Enquanto você entra para escrever o aviso, outras pessoas também entram:
algumas apenas leem o quadro,
outras rabiscam algo,
outras apagam informações.
Você faz o que o professor pediu, sai tranquilo e avisa que está tudo certo.
Mais tarde, você volta para conferir… e o aviso não está mais lá. Alguém entrou depois de você e alterou o quadro antes da hora.
Ninguém fez isso “por mal”. O problema é que todo mundo podia entrar e mexer ao mesmo tempo, sem nenhuma coordenação.
Essa é a essência da concorrência: várias pessoas (ou threads) acessando e modificando o mesmo recurso ao mesmo tempo, sem controle, gerando resultados imprevisíveis.
E se houvesse alguém controlando a entrada?
Agora imagine a mesma sala, mas com um detalhe importante: há um segurança em cada porta.
A regra dele é simples:
para escrever no quadro, só entra uma pessoa por vez;
enquanto alguém está escrevendo, os outros esperam;
o aviso do professor fica lá até a hora certa.
Você entra, escreve o aviso, sai. Até as 15h, que é a hora da aula e o aviso deixa de fazer sentido, as pessoas apenas leem. Quando chega o horário, outro aluno ou professor entra, apaga e escreve o aviso dele.
Quando você volta para conferir, o quadro está exatamente como deveria estar.
Essa coordenação simples muda tudo.
Fazendo o paralelo com Java
Em Java, o synchronized cumpre exatamente esse papel do segurança:
ele controla o acesso a um recurso compartilhado;
garante que apenas uma thread por vez execute um trecho crítico;
evita que o estado do sistema fique inconsistente.
Ele não torna o sistema mais rápido — pelo contrário, ele faz as threads esperarem. Mas ele torna o sistema correto, previsível e confiável.
Concluindo…
Concorrência não é, por si só, o problema. O problema é concorrência sem coordenação.
Sem regras, vira bagunça. Com um mínimo de controle, a informação passa a fazer sentido.
E, muitas vezes, é exatamente isso que o synchronized está fazendo no seu código: não deixando todo mundo entrar na sala ao mesmo tempo.
2025 foi um ano marcante na minha carreira — não por grandes viradas visíveis, mas pelo que ele representou em termos de consolidação, amadurecimento e clareza.
Foi um ano em que deixei de apenas “executar bem” para começar a compreender, de forma mais profunda, o que realmente significa construir uma carreira de longo prazo — com responsabilidade, resiliência e intenção.
Crescimento técnico e mudança de perspectiva
Ao longo de 2025, atuei no time de Orquestração de uma grande empresa de mídia do Brasil, trabalhando no back-end com Java, Spring e Camunda, em aplicações críticas responsáveis por integrações complexas dentro de uma jornada de negócios relevante.
Foi um período intenso, de muito aprendizado técnico, convivência com sistemas de alta complexidade e responsabilidade real.
Um dos maiores desafios do ano foi a transição da sustentação para o desenvolvimento. Mesmo deixando oficialmente a sustentação, eu ainda carregava o olhar e o comportamento de quem sempre foi referência nesse tema. Isso, em alguns momentos, dificultou meu foco total no desenvolvimento e me trouxe aprendizados importantes sobre desapego, mudança de mentalidade e reposicionamento profissional.
Promoção e aumento de responsabilidade
Em junho de 2025, fui promovido para Custom Software Engineering Specialist (CL9). Foi uma conquista muito batalhada, construída ao longo de anos, com consistência, entrega e apoio próximo da minha liderança.
A promoção não mudou radicalmente o dia a dia na prática, mas mudou as expectativas e o nível de responsabilidade. Ficou claro para mim que, a partir dali, não bastava apenas cumprir bem o papel técnico — era necessário agir desde já no próximo nível, com mais visão, postura e impacto.
Primeiros passos reais na liderança
2025 também marcou meu início formal na liderança, atuando como People Lead pela primeira vez. Foi — e continua sendo — uma experiência transformadora.
Na prática, aprendi que liderar vai muito além de técnica ou boa intenção. É difícil acompanhar de perto, definir metas claras, manter alguém motivado continuamente e, ao mesmo tempo, entender que não é possível — nem saudável — fazer tudo pelo outro.
Esse ano confirmou algo importante para mim: liderar pessoas é, sim, o próximo passo que quero dar, com responsabilidade, cuidado humano e foco no crescimento real das pessoas e na entrega de valor para os clientes da Accenture.
Transição de time e resiliência
Já no final de 2025, vivi uma transição importante: saí do time de Orquestração e passei a atuar no time de Marketing Cloud, dentro do mesmo contexto corporativo, migrando de um cenário B2C para B2B.
Foi uma decisão organizacional, comunicada de forma planejada, e que exigiu maturidade emocional e profissional. A mudança trouxe um novo desafio técnico: passei a atuar no front-end, desenvolvendo Landing Pages hospedadas no Salesforce CloudPages, tendo meu primeiro contato mais profundo com Data Extensions e o ecossistema Salesforce.
Mais do que a mudança em si, esse momento me ensinou sobre resiliência, calma e confiança no processo, mesmo diante de incertezas.
Aprendizados que levo comigo
Se eu tivesse que resumir 2025 em um aprendizado central, seria este:
Em 2025, aprendi que construir uma carreira sólida exige tempo, responsabilidade e escolhas conscientes.
Agradecimentos
Nada do que construí em 2025 teria sido possível sem pessoas que caminharam comigo ao longo desse processo.
Agradeço à minha liderança, que confiou no meu trabalho, me apoiou nos momentos de transição e contribuiu diretamente para meu crescimento profissional dentro da Accenture.
Também sou grato aos times com os quais atuei ao longo do ano, pelas trocas, aprendizados, desafios compartilhados e pela colaboração diária, que foram fundamentais para minha evolução técnica e profissional.
Tive contato com muitas pessoas ao longo desse período, e cada interação contribuiu, de alguma forma, para a construção da minha trajetória em 2025.
Encerramento
2025 não foi sobre velocidade. Foi sobre base, consciência e direção.
Levo esses aprendizados comigo para 2026, com ainda mais clareza de quem eu sou hoje — e de quem quero me tornar.
Quando lidamos com sistemas complexos, um dos maiores desafios é compreender o negócio de forma organizada. O Domain-Driven Design (DDD) propõe que, antes mesmo de pensar em código, precisamos entender profundamente o domínio — ou seja, o problema central que o software deseja resolver. Dentro desse domínio, existem partes menores e especializadas: os subdomínios.
Vaughn Vernon, em Domain-Driven Design Destilado, reforça que identificar subdomínios é um dos passos fundamentais para criar sistemas coerentes, expressivos e mais fáceis de evoluir.
Por que subdomínios existem?
Um negócio de verdade não é monolítico. Ele é composto por diversas capacidades, processos e responsabilidades distintas. Os subdomínios representam exatamente isso: segmentos do negócio que possuem objetivos e regras próprias.
Dividir o domínio em subdomínios ajuda a enxergar melhor as partes importantes, reduz confusões conceituais e prepara o terreno para decisões arquiteturais melhores — como os Bounded Contexts.
Três tipos de subdomínios
Vaughn Vernon destaca três categorias que ajudam a entender o papel de cada parte do negócio:
1. Subdomínio Core (Core Domain)
É o coração do negócio, aquilo que realmente diferencia a empresa no mercado. É onde você investe mais esforço de modelagem, especialistas do negócio e design cuidadoso.
Exemplo: Em uma plataforma de investimentos, o “motor de cálculo de risco e rentabilidade” pode ser o core domain. É a inteligência que torna a plataforma melhor que a concorrência.
2. Subdomínios de Suporte (Supporting Subdomains)
São importantes para que o core funcione bem, mas não representam diferencial competitivo. Têm regras próprias, mas servem principalmente para dar sustentação ao core.
Exemplo: Ainda na plataforma de investimentos, áreas como “gestão de clientes” ou “atualização cadastral” são essenciais, porém não definem inovação. São processos que precisam estar corretos, mas não precisam de modelagem profunda como o core.
3. Subdomínios Genéricos (Generic Subdomains)
São capacidades que quase todo negócio precisa e não valem o esforço de reinventar. Normalmente são resolvidos com bibliotecas, frameworks ou serviços já existentes.
Exemplo: Autenticação, envio de notificações por e-mail, controle de acesso. Faz sentido usar soluções consolidadas em vez de construir tudo do zero.
Como identificar subdomínios na prática?
A análise começa conversando com especialistas do negócio, entendendo processos reais e observando onde estão as diferenças de linguagem, objetivos e regras. Subdomínios costumam aparecer quando:
uma parte do negócio tem linguagem própria (“risco”, “perfil”, “vector de exposição” são típicos do domínio financeiro)
o processo tem etapas e decisões específicas
a responsabilidade daquela área é clara e independente das demais
O segredo é olhar para o negócio como um mapa: cada região desse mapa é um subdomínio com fronteiras conceituais claras.
Exemplos de subdomínios em diferentes áreas
E-commerce
Core: estratégia de precificação, recomendação de produtos
Suporte: catálogo, inventário, pagamentos
Genérico: autenticação, geração de boletos, envio de e-mails
Aplicativo de entrega
Core: sistema de roteamento inteligente e previsão de entrega
Suporte: cadastro de restaurantes, avaliações
Genérico: login, monitoramento de logs
Banco digital
Core: motor de aprovação de crédito, análise de risco
Suporte: abertura de conta, operações de cartões
Genérico: envio de SMS, verificação de identidade via terceiros
Esses exemplos mostram que o “core” nunca é o sistema inteiro, mas sim aquele pedaço onde a empresa se diferencia.
Subdomínio não é Bounded Context
É comum confundir os dois, mas eles têm papéis diferentes:
Subdomínio → existe no negócio
Bounded Context → existe na modelagem do software
Ou seja, primeiro entendemos o negócio por meio de subdomínios; depois, ao transformar isso em software, criamos bounded contexts para representar esses conceitos dentro de limites claros.
Conclusão
Subdomínios são a primeira grande divisão lógica dentro do domínio de um negócio. Eles ajudam a enxergar prioridades, planejar melhor o design e decidir onde vale investir mais esforço. Seguindo o raciocínio de Vaughn Vernon, reconhecer o que é core, o que é suporte e o que é genérico permite que a equipe concentre energia naquilo que realmente importa e simplifique o que pode ser reaproveitado.
Dominar esse conceito é abrir caminho para aplicar o restante do DDD com muito mais clareza e propósito — especialmente quando chega o momento de definir bounded contexts e arquiteturas alinhadas ao domínio.
Domain-Driven Design (DDD) é uma abordagem que coloca o domínio — as regras, conceitos e processos essenciais do negócio — no centro das decisões de software. Embora seus princípios possam ser aplicados em diversos estilos arquiteturais, algumas arquiteturas dialogam de forma especialmente natural com o DDD, pois favorecem isolamento de responsabilidades, clareza de limites e evolução contínua. A seguir, exploramos essas arquiteturas, como elas fortalecem o DDD e quais livros ajudam a aprofundar cada tema.
Event-Driven Architecture (EDA)
Em muitos domínios, eventos representam mudanças relevantes: um pedido é criado, um pagamento é aprovado, um contrato expira. A Event-Driven Architecture transforma esses acontecimentos em mensagens explícitas, permitindo que diferentes Bounded Contexts se comuniquem sem acoplamento direto.
Essa abordagem combina de maneira orgânica com Domain Events do DDD, favorecendo autonomia e escalabilidade dentro de sistemas distribuídos.
Livro recomendado:Implementing Domain-Driven Design, de Vaughn Vernon — que integra eventos ao design tático e estratégico do DDD.
Command Query Responsibility Segregation (CQRS)
CQRS separa a responsabilidade de escrita (comandos) da responsabilidade de leitura (consultas). Essa divisão reduz conflitos entre regras de negócio e necessidades de consulta, tornando o modelo de domínio mais limpo e focado.
Em DDD, CQRS permite que o modelo de domínio represente comportamentos e invariantes com clareza, enquanto os modelos de leitura são moldados para atender demandas específicas de visualização ou desempenho.
Livro recomendado: Não há um livro único e oficial sobre CQRS, mas os materiais e workshops de Greg Young — criador do padrão — são as melhores referências.
Actor Model e Arquiteturas Reativas
Em arquiteturas reativas baseadas no Actor Model, cada componente isola seu estado e se comunica exclusivamente por mensagens. Essa abordagem reduz riscos de concorrência e facilita modelagem de comportamentos distribuídos.
No contexto de DDD, atores podem representar entidades ou agregados, e o fluxo de mensagens se alinha naturalmente a políticas do domínio. Essa combinação é especialmente útil em sistemas que lidam com grandes volumes de eventos simultâneos.
Livro recomendado:Reactive Messaging Patterns with the Actor Model, de Vaughn Vernon.
REST-Based Architecture
REST continua sendo um dos estilos mais populares para expor capacidades de sistemas modernos. Ele estrutura recursos em torno de representações simples e previsíveis, facilitando integração entre diversos contextos.
Quando usado dentro de limites bem definidos, REST funciona como uma porta estável de comunicação para um Bounded Context, sem comprometer a expressividade interna do modelo de domínio.
Livro recomendado:RESTful Web Services, de Leonard Richardson e Sam Ruby.
Service-Oriented Architecture (SOA)
SOA introduziu a ideia de serviços autônomos, orientados a capacidades específicas do negócio. Esses princípios ecoam diretamente a noção de Bounded Contexts no DDD.
Embora SOA costume ser aplicado em ambientes corporativos amplos, sua insistência em contratos, interoperabilidade e limites bem definidos reforça práticas essenciais do DDD.
Livro recomendado:SOA Principles of Service Design, de Thomas Erl.
Microservices Architecture
A arquitetura de microservices ganhou força por dividir sistemas em serviços pequenos e independentes. Porém, sem entendimento claro de limites, microservices facilmente se tornam fragmentação acidental.
No DDD, esses serviços devem nascer de Bounded Contexts. Quando existe um alinhamento entre limites do domínio e limites do serviço, microservices oferecem autonomia real, escalabilidade e evolução descentralizada.
Livro recomendado:Building Microservices, de Sam Newman — uma visão prática, combinável com o DDD. Para padrões avançados, Microservices Patterns, de Chris Richardson.
Hexagonal Architecture (Ports and Adapters)
A Arquitetura Hexagonal, ou Ports and Adapters, separa o núcleo de domínio das dependências externas. O domínio fica protegido de detalhes técnicos, bancos, frameworks ou protocolos de comunicação.
Esse isolamento permite que o modelo de domínio evolua livremente, reforçando a centralidade do negócio e tornando o software mais testável e adaptável. Essa arquitetura é especialmente eficaz quando combinada com os padrões táticos do DDD.
Livro recomendado:Implementing Domain-Driven Design, de Vaughn Vernon. Para referência conceitual original, os textos de Alistair Cockburn sobre Ports and Adapters.
Conclusão
Cada arquitetura apresentada reforça, à sua maneira, os princípios do Domain-Driven Design. Event-Driven Architecture evidencia acontecimentos importantes do negócio; CQRS organiza responsabilidades de forma clara; o Actor Model fortalece sistemas concorrentes e orientados a mensagens; REST facilita integração entre contextos; SOA e microservices dão forma explícita aos limites contextuais; e a Arquitetura Hexagonal protege o domínio das pressões externas.
Quando combinadas com discernimento, essas abordagens ampliam a capacidade de um sistema representar o negócio com precisão, evoluir com segurança e permanecer compreensível com o tempo. É justamente nessa interseção entre arquitetura e domínio que o DDD atinge seu potencial máximo.
Quando um sistema cresce, seus conceitos começam a se repetir em diferentes áreas da aplicação. Muitas vezes, a mesma palavra passa a significar coisas distintas dependendo de onde é usada. Essa sobreposição de significados cria modelos confusos, entidades infladas e código difícil de manter. O Bounded Context surgiu justamente para evitar esse tipo de problema.
A imagem evidencia a ideia central do bounded context: cada parte do domínio tem suas próprias regras, comportamentos e linguagem interna. Nada está misturado ou confuso; os mundos coexistem lado a lado, independentes e ao mesmo tempo integráveis pelos pontos certos.
Bounded Context?
Um Bounded Context (Contexto Delimitado) é uma fronteira clara onde um conjunto de conceitos, regras e modelos tem um significado único e consistente.
Dentro dessa fronteira:
as palavras são usadas com precisão;
o modelo é criado apenas para resolver as necessidades daquele contexto;
não há obrigação de carregar significados de outros lugares do sistema.
Fora desse limite, os mesmos termos podem ter definições diferentes, e isso é desejável. Cada contexto descreve apenas a parte do domínio que realmente lhe pertence.
Por que usar Bounded Contexts
A separação do domínio em bounded contexts ajuda a:
reduzir ambiguidades no significado dos conceitos;
evitar modelos inflados e genéricos;
diminuir dependências indevidas entre áreas do sistema;
permitir que cada parte evolua com clareza e foco.
Essa abordagem torna o software mais compreensível e mais fácil de manter ao longo do tempo.
Vamos a um exemplo simples
Imagine uma plataforma de ensino.
Contexto de catálogo
O objetivo é exibir cursos ao usuário.
O modelo Curso pode conter:
título
descrição
carga horária
categoria
Esse contexto se preocupa apenas com apresentação.
Contexto de matrículas
Aqui, Curso representa outra realidade:
quantidade de vagas
período de matrícula
regras de elegibilidade
status da turma
O foco é controlar quem pode se matricular e quando.
É a mesma palavra (Curso), mas com significados diferentes. Cada contexto preserva seu próprio uso do conceito, sem interferências desnecessárias.
Agora segue um exemplo de quando não existe Bounded Context
Sem dividir por contextos, é comum surgir uma única entidade chamada Curso contendo todos os campos de todas as áreas:
título, descrição e carga horária
vagas e períodos
preços
regras administrativas
métricas internas
requisitos e calendários
status de matrícula
Esse acúmulo cria:
complexidade desnecessária;
propriedades que só fazem sentido para parte do sistema;
validações confusas;
impacto imprevisível quando a entidade é alterada.
Bounded Context evita justamente essa mistura de significados.
Dúvidas comuns
Uma aplicação deve ter quantos Bounded Contexts?
Não existe uma regra fixa. O domínio é quem define as fronteiras.
Quando há apenas um contexto
Projetos pequenos, MVPs e domínios simples podem começar com um único contexto. Separar cedo demais traz complexidade artificial.
Quando há vários contextos
Em sistemas reais, é comum existir mais de um. Isso ocorre quando:
diferentes áreas do sistema usam o mesmo termo com significados distintos;
regras de negócio são muito específicas para cada área;
modelos ficariam grandes demais se unidos.
É natural, e até esperado, que um software maduro tenha múltiplos bounded contexts.
Os bounded contexts precisam ser aplicações separadas?
Não necessariamente. Existem duas formas de organizá-los:
1. Vários bounded contexts na mesma aplicação
Funciona bem quando:
o sistema ainda não exige escalabilidade independente;
a equipe é pequena;
os contextos ainda evoluem juntos.
Nesse caso, a separação é lógica: pastas, módulos, camadas.
2. Cada bounded context como um serviço independente
Acontece quando:
os contextos são grandes;
equipes trabalham separadas;
há necessidade de autonomia e deploy independente.
Isso geralmente aparece em arquiteturas de microsserviços, mas só é recomendado quando existe independência real entre contextos.
E o repositório Git? Monorepo ou Multirepo?
A escolha depende do nível de independência dos bounded contexts.
Monorepo (um único repositório)
Recomendado quando:
os contextos estão na mesma aplicação;
mudanças frequentemente envolvem mais de um contexto;
equipes são pequenas.
Facilita refatoração e manutenção.
Multirepo (um repositório por contexto)
Faz sentido quando:
cada contexto é um serviço separado;
equipes diferentes mantêm contextos distintos;
ciclos de deploy são independentes.
Traz autonomia, mas aumenta a necessidade de contratos estáveis e comunicação clara entre serviços.
Recomendações práticas
Deixe o domínio apontar onde os contextos começam e terminam.
Só separe quando existir diferença real de significado ou regras.
Não transforme cada contexto em um serviço isolado sem necessidade.
Prefira monorepo para projetos pequenos ou médios.
Use multirepo apenas quando autonomia e deploy independente forem requisitos do domínio.
Conclusão
O Bounded Context é uma ferramenta essencial para manter sistemas compreensíveis conforme crescem. Ele funciona como um mapa que impede que conceitos se misturem, garantindo que cada parte do domínio tenha seu próprio significado, suas próprias regras e seu próprio ritmo de evolução. Essa clareza reduz atrito entre equipes, diminui ambiguidades e preserva a saúde do modelo ao longo do tempo.
Nem todo software precisa começar com vários bounded contexts. Em sistemas pequenos ou em fases iniciais, um único contexto costuma ser suficiente e até desejável. A divisão se torna realmente importante quando o domínio cresce a ponto de a mesma palavra significar coisas diferentes, quando regras de negócio se tornam complexas em áreas distintas, ou quando o modelo passa a ficar pesado demais para representar tudo de uma só vez.
Quando bem aplicados, os bounded contexts ajudam o software a refletir de forma mais fiel a realidade do negócio, evitando acoplamentos desnecessários e permitindo que cada parte evolua no seu próprio ritmo. Essa prática não é apenas uma escolha arquitetural: é uma maneira de manter o domínio saudável, o código sustentável e a comunicação entre equipes mais clara — três pilares fundamentais em qualquer produto que pretende sobreviver ao tempo e à complexidade inevitável de sistemas vivos.