0Pricing
PHP Academy · Aula

Do monólito aos microsserviços

Decida o que dividir e como definir os limites dos serviços.

Do monólito aos microsserviços é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.

Do monólito aos microsserviços

Microsserviços são uma aposta organizacional e operacional, não uma escolha padrão. Dividir um monólito PHP troca a simplicidade no mesmo processo por chamadas de rede, dados distribuídos e complexidade de implantação. Quando feito pelas razões erradas, torna tudo mais lento.

Esta lição trata da parte mais difícil: definir os limites dos serviços. Acerte as separações e o restante será apenas infraestrutura; erre-as e você construirá um monólito distribuído — com todo o custo e nenhum benefício.

Por que (e por que não) dividir

Boas razões para dividir:

  • Implantação independente e responsabilidade independente das equipes.
  • Escalonamento independente dos subsistemas mais exigidos.
  • Isolamento de tecnologia/tempo de execução e contenção de falhas.

Más razões: "o código está desorganizado" (refatore primeiro o monólito) ou seguir uma tendência. Se dois serviços precisam sempre ser implantados juntos ou compartilham uma tabela do banco de dados, eles são um único serviço com dois papéis.

Contextos delimitados

O Design Orientado ao Domínio oferece a ferramenta mais precisa para definir limites: o contexto delimitado. Dentro de um contexto, os termos têm um único significado preciso. "Cliente" em Faturamento (o destinatário de uma fatura) é diferente de "Cliente" em Suporte (o autor de um chamado).

Cada contexto delimitado é um forte candidato a se tornar um serviço. Os limites seguem a linguagem do negócio e a forma como a organização realmente se comunica — a Lei de Conway em ação.

Alta coesão, baixo acoplamento

Um bom limite de serviço mantém dentro dele as coisas que mudam em conjunto e deixa de fora as que mudam de forma independente. Avalie uma divisão proposta considerando:

  • Quantas funcionalidades exigem alterar dois serviços ao mesmo tempo? (Deve ser um número pequeno.)
  • Quão excessivamente comunicativo é o padrão de chamadas entre eles? (Deve ter uma granularidade mais grossa.)

Se implementar uma funcionalidade atravessa constantemente um limite, o limite está no lugar errado.

<?php
// Chatty boundary smell: N network calls to render one view
foreach ($order->lineItems as $item) {
    $product = $catalogApi->get($item->productId); // one call PER item!
    $names[] = $product['name'];
}

// Coarse-grained: one batch call across the boundary
$ids   = array_map(fn($i) => $i->productId, $order->lineItems);
$names = $catalogApi->getMany($ids); // single round-trip
echo count($names) . " products in one call\n";

Um banco de dados por serviço

A regra inegociável: cada serviço é responsável pelos próprios dados e nenhum outro serviço acessa suas tabelas. Bancos de dados compartilhados recriam o acoplamento que você tentou eliminar — uma alteração no esquema quebra serviços não relacionados.

Isso significa que consultas entre serviços que eram uma operação SQL JOIN no monólito se tornam chamadas de API ou modelos de leitura replicados. Esse é o preço — e esse é justamente o objetivo.

<?php
// In the monolith: one JOIN across domains
$sql = 'SELECT o.id, c.email
        FROM orders o JOIN customers c ON c.id = o.customer_id';

// After split: Orders service holds only the foreign id;
// it asks the Customers service for the rest (or keeps a local read model).
$order = $orderRepo->find($id);          // local
$customer = $customersApi->get($order->customerId); // network call
echo $order->id . ' / ' . $customer->email . "\n";

O padrão da figueira estranguladora

Nunca reescreva um monólito de uma só vez. O padrão da figueira estranguladora faz a extração de forma incremental: encaminhe uma parte do tráfego para um novo serviço por meio de uma fachada/proxy, amplie-o e só retire o caminho de código antigo quando o novo o cobrir completamente.

Um proxy reverso (ou uma porta de entrada da API) fica à frente e decide, para cada rota, se deve acessar o monólito legado ou o novo serviço. A migração avança uma capacidade por vez, sempre pronta para ser entregue.

<?php
// Facade routing: peel off one capability at a time
function route(string $path): string {
    $migrated = ['/invoices', '/invoices/pdf']; // moved to billing-svc
    foreach ($migrated as $prefix) {
        if (str_starts_with($path, $prefix)) {
            return 'http://billing-svc' . $path;
        }
    }
    return 'http://legacy-monolith' . $path; // everything else, for now
}
echo route('/invoices/pdf'), "\n";
echo route('/users/42'), "\n";

Extraindo um módulo

Uma ordem prática para a extração:

  1. Encontre um módulo com poucas dependências de entrada e responsabilidade clara pelos dados.
  2. Primeiro, encapsule suas chamadas no mesmo processo por trás de uma interface no monólito.
  3. Mova os dados sob sua responsabilidade para o próprio esquema/banco de dados.
  4. Substitua a implementação da interface por um cliente de rede.
  5. Redirecione o tráfego por meio da fachada e exclua o código antigo.

Fazer o encapsulamento da interface dentro do monólito primeiro reduz os riscos da etapa de rede.

<?php
// Step 2: hide the implementation behind a port the monolith calls
interface InvoiceService {
    public function generate(string $orderId): string; // returns invoice id
}

// Today: local class. Tomorrow: HTTP client to billing-svc.
// The monolith's calling code never changes.
final class LocalInvoiceService implements InvoiceService {
    public function generate(string $orderId): string { return 'inv-1'; }
}

Consistência de dados distribuídos

Depois que os dados são divididos, você perde as transações ACID entre serviços. Adote a consistência eventual: os serviços publicam eventos sobre os próprios dados, e os demais constroem modelos de leitura locais a partir desses eventos.

O serviço de Pedidos não consulta o serviço de Clientes em todas as requisições — ele mantém uma pequena projeção (apenas os campos de que precisa), atualizada por eventos CustomerUpdated. Isso remove uma dependência em tempo de execução e um salto de latência.

<?php
// Orders service keeps a tiny local projection of customer data
function onCustomerUpdated(PDO $db, array $evt): void {
    $db->prepare(
        'INSERT INTO customer_read_model (id, email)
         VALUES (:id, :email)
         ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email'
    )->execute(['id' => $evt['id'], 'email' => $evt['email']]);
}

Realidade operacional

Os microsserviços transferem a complexidade do código para as operações. Antes de dividir, você precisa de:

  • Registro em log centralizado e rastreamento distribuído (identificadores de correlação entre os saltos).
  • CI/CD por serviço e implantações independentes e versionadas.
  • Verificações de integridade, tempos limite, novas tentativas e disjuntores em todas as chamadas.
  • Testes de contrato para que um provedor não possa quebrar silenciosamente um consumidor.

Se sua equipe não consegue operar bem um serviço, operar dez será dez vezes pior.

Dimensionamento adequado dos serviços

O termo "micro" é enganoso — dimensione os serviços pela capacidade de negócio e responsabilidade da equipe, não pelas linhas de código. Com uma granularidade fina demais (nanosserviços), uma única funcionalidade se espalha por uma tempestade de chamadas de rede; com uma granularidade grossa demais, você volta a ter um monólito.

Uma boa regra prática: um serviço deve poder ser assumido por uma equipe, ser implantável por conta própria e conseguir atender seus principais casos de uso sem uma cadeia síncrona que atravesse muitos serviços pares.

A alternativa do monólito modular

Antes de distribuir o sistema, considere o monólito modular: uma única unidade implantável, mas dividida internamente em módulos com limites explícitos e esquemas próprios, que se comunicam apenas por meio de interfaces publicadas — sem acesso a tabelas de outros módulos.

Você obtém limites bem definidos e refatoração fácil sem o custo adicional dos sistemas distribuídos. Quando um módulo realmente precisa de escalabilidade ou responsabilidade independentes, ele já está estruturado para ser extraído pelo padrão da figueira estranguladora. Para a maioria das equipes, este é o primeiro passo correto.

<?php
// Modules talk only through interfaces, never each other's tables.
namespace App\Billing;          // owns billing_* tables
interface BillingFacade {
    public function invoiceForOrder(string $orderId): string;
}

namespace App\Sales;            // owns sales_* tables
final class Checkout {
    public function __construct(private \App\Billing\BillingFacade $billing) {}
    // Sales never SELECTs from billing_* directly - only via the facade.
}

Verificação rápida

Reconhecendo uma divisão ruim.

Recapitulação

Definindo bem os limites dos serviços:

  • Divida por capacidade de implantação, escalabilidade e responsabilidade — não porque o código está desorganizado.
  • Alinhe os limites aos contextos delimitados; busque alta coesão e baixo acoplamento.
  • Um banco de dados por serviço — sem tabelas compartilhadas; substitua as operações JOIN por APIs ou modelos de leitura.
  • Migre de forma incremental com o padrão da figueira estranguladora.
  • Aceite a consistência eventual e invista nas operações antes de ampliar o sistema.

A seguir: como esses serviços realmente se comunicam — REST e gRPC.

Perguntas Frequentes

A aula “Do monólito aos microsserviços” é grátis?

Sim — o texto completo de “Do monólito aos microsserviços” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.

O que vou aprender em “Do monólito aos microsserviços”?

Decida o que dividir e como definir os limites dos serviços. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar PHP Academy?

Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Do monólito aos microsserviços”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de PHP Academy?

Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Do monólito aos microsserviços
  2. Comunicação entre serviços: REST e gRPC
  3. Gateways de API e descoberta de serviços
  4. Resiliência: disjuntores e novas tentativas
← Voltar para PHP Academy