<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>escalabilidade Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<atom:link href="https://leonardonascimento.dev/tag/escalabilidade/feed/" rel="self" type="application/rss+xml" />
	<link>https://leonardonascimento.dev/tag/escalabilidade/</link>
	<description>Especializado em backend, APIs e sistemas escaláveis. Experiência em arquitetura de sistemas, integrações, mensageria, performance e aplicações de alta disponibilidade.</description>
	<lastBuildDate>Thu, 22 Jan 2026 14:58:41 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://leonardonascimento.dev/wp-content/uploads/2021/05/cropped-programming-32x32.png</url>
	<title>escalabilidade Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<link>https://leonardonascimento.dev/tag/escalabilidade/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Rate limiting em APIs: por que é obrigatório em produção</title>
		<link>https://leonardonascimento.dev/blog/rate-limiting-em-apis-por-que-e-obrigatorio-em-producao/</link>
					<comments>https://leonardonascimento.dev/blog/rate-limiting-em-apis-por-que-e-obrigatorio-em-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Mon, 12 Jan 2026 14:55:11 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[apis]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[escalabilidade]]></category>
		<category><![CDATA[produção]]></category>
		<category><![CDATA[rate limiting]]></category>
		<category><![CDATA[segurança]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2285</guid>

					<description><![CDATA[<p>Rate limiting quase sempre entra na conversa tarde demais. Normalmente depois do primeiro pico inesperado, de uma integração mal-comportada ou de um endpoint que começa a consumir recursos de forma descontrolada. Em ambiente local, nada disso aparece. Em produção, aparece rápido. API sem rate limiting não é API aberta. É API frágil. Em produção, você [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/rate-limiting-em-apis-por-que-e-obrigatorio-em-producao/">Rate limiting em APIs: por que é obrigatório em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><a href="https://leonardonascimento.dev/tag/api/" type="post_tag" id="210">Rate limiting</a> quase sempre entra na conversa tarde demais. Normalmente depois do primeiro pico inesperado, de uma integração mal-comportada ou de um endpoint que começa a consumir recursos de forma descontrolada. Em ambiente local, nada disso aparece. Em produção, aparece rápido.</p>



<p><a href="https://leonardonascimento.dev/blog/erros-comuns-em-apis-que-causam-problemas-em-producao/" type="post" id="2248">API sem rate limiting não é API aberta. É API frágil.</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Em produção, você não controla quem consome sua API nem como ela será usada. Mesmo quando o consumidor é “conhecido”, basta um loop mal implementado, um retry agressivo ou um bug simples para gerar milhares de requisições em poucos segundos. Sem limitação, a aplicação tenta atender tudo ao mesmo tempo e começa a degradar de forma silenciosa até parar.</p>



<p>Rate limiting não existe para punir usuários. Ele existe para <strong>proteger o sistema</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>O primeiro ponto é <strong>estabilidade</strong>. Uma API precisa continuar respondendo mesmo sob carga anormal. Quando não há limite, uma única origem pode consumir CPU, conexões e threads a ponto de afetar todos os outros consumidores. Com rate limiting, você isola impacto: quem exagera sofre limitação, quem usa corretamente continua funcionando.</p>



<p>Em outras palavras, rate limiting é um mecanismo de contenção de danos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Outro aspecto importante é <strong>previsibilidade</strong>. Em produção, você precisa saber até onde o sistema aguenta. Sem limites, o comportamento sob estresse é imprevisível: timeouts aleatórios, filas acumulando, banco sobrecarregado. Com rate limiting, o sistema passa a falhar de forma controlada, retornando erro claro e mantendo o restante da aplicação saudável.</p>



<p>Falhar rápido e de forma explícita é muito melhor do que degradar tudo lentamente.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Rate limiting também é uma <strong>camada básica de segurança</strong>. Não substitui autenticação nem autorização, mas reduz muito a superfície de ataque. Tentativas de força bruta, scraping agressivo e abusos simples ficam automaticamente limitados. Mesmo ataques não intencionais, como integrações mal configuradas, deixam de causar impacto sistêmico.</p>



<p>Segurança em produção não é só impedir acesso indevido, é impedir uso destrutivo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Em APIs que lidam com <strong><a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/" type="post" id="2262">integrações externas</a></strong>, rate limiting se torna ainda mais crítico. Muitas integrações fazem retry automático quando recebem erro ou timeout. Sem limite, isso vira efeito cascata: o sistema fica lento, responde pior, recebe mais retries e entra em colapso. Limitar requisições ajuda a quebrar esse ciclo e manter o sistema respirando.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Existe também o aspecto de <strong>justiça entre consumidores</strong>. Em APIs públicas ou compartilhadas, sem rate limiting um consumidor pode consumir recursos de forma desproporcional. Com limites bem definidos, você garante que ninguém monopolize a capacidade do sistema. Isso é especialmente importante quando existem planos, SLAs ou diferentes níveis de acesso.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Um erro comum é pensar que rate limiting só serve para APIs públicas. Isso não é verdade. APIs internas, usadas por múltiplos serviços ou múltiplos clientes, também precisam de limite. Em produção, erros internos são tão perigosos quanto abusos externos.</p>



<p>Outro erro frequente é implementar rate limiting apenas no gateway ou apenas na aplicação, sem pensar no conjunto. Em sistemas maiores, o ideal é ter defesa em camadas: alguma limitação na borda e alguma consciência de limite dentro da aplicação.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Rate limiting também ajuda na <strong>observabilidade</strong>. Quando bem configurado, ele vira sinal. Se muitos consumidores começam a bater no limite, isso indica mudança de comportamento, bug novo ou crescimento não previsto. Ignorar esses sinais é perder uma oportunidade de agir antes do problema escalar.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Vale reforçar: rate limiting não deve ser arbitrário. Limites precisam fazer sentido para o tipo de operação, o perfil de uso e a capacidade do sistema. Endpoints críticos e pesados precisam de limites mais restritos do que endpoints simples. Ajustar isso faz parte do amadurecimento da API.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="h-conclusao">Conclusão</h2>



<p>Rate limiting não é detalhe, não é “nice to have” e não é algo que se adiciona depois. Em produção, ele é requisito básico de estabilidade, segurança e previsibilidade. APIs que não limitam uso estão sempre a um passo de um incidente difícil de explicar e mais difícil de corrigir.</p>



<p>Quem projeta APIs pensando em produção entende que proteger o sistema é tão importante quanto fazê-lo funcionar.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/rate-limiting-em-apis-por-que-e-obrigatorio-em-producao/">Rate limiting em APIs: por que é obrigatório em produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/rate-limiting-em-apis-por-que-e-obrigatorio-em-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Boas práticas para estruturar projetos em Laravel de médio e grande porte</title>
		<link>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/</link>
					<comments>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Wed, 07 Jan 2026 14:12:16 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[arquitetura]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código sustentável]]></category>
		<category><![CDATA[escalabilidade]]></category>
		<category><![CDATA[estrutura de projeto]]></category>
		<category><![CDATA[laravel]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2262</guid>

					<description><![CDATA[<p>Quando o projeto Laravel é pequeno, quase qualquer organização funciona. Você cria controllers, models, requests, alguns services, resolve tudo no “app/” e segue. O problema começa quando o sistema cresce: mais módulos, mais regras, integrações, filas, diferentes times mexendo no mesmo lugar… e, de repente, o que era simples vira uma base difícil de evoluir. [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/">Boas práticas para estruturar projetos em Laravel de médio e grande porte</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Quando o projeto <a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Laravel </a>é pequeno, quase qualquer organização funciona. Você cria controllers, models, requests, alguns services, resolve tudo no “app/” e segue. O problema começa quando o sistema cresce: mais módulos, mais regras, integrações, filas, diferentes times mexendo no mesmo lugar… e, de repente, o que era simples vira uma base difícil de evoluir.</p>



<p>Estruturar um projeto Laravel bem não é sobre “<a href="https://leonardonascimento.dev/categoria/arquitetura/" type="category" id="217">inventar arquitetura</a>”. É sobre reduzir atrito: facilitar manutenção, evitar acoplamento desnecessário e deixar o código previsível para quem chega depois.</p>



<p>A seguir estão práticas que funcionam bem em projetos médios e grandes, especialmente quando já existe operação de produção, roadmap e mudanças frequentes.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Comece pela regra: controller não é lugar de lógica</h2>



<p>Controller deveria orquestrar: receber request, validar, chamar a camada certa e responder. Quando regra de negócio fica no controller, você cria um ponto de acoplamento difícil de testar e difícil de reutilizar. Em projeto grande isso vira padrão ruim rapidamente, porque todo mundo copia o que já existe.</p>



<p>O que funciona melhor é mover lógica para classes dedicadas (services/use cases/actions), e deixar o controller como uma “casca” fina. Você ganha clareza, reaproveitamento e testes mais simples.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Estruture por domínio (feature) quando o sistema crescer</h2>



<p>A estrutura padrão do Laravel (Controllers, Models, Jobs, etc.) é ótima até um certo ponto. Em sistemas grandes, ela tende a espalhar a mesma funcionalidade por várias pastas e o dev precisa “caçar” arquivos para entender um fluxo.</p>



<p>Uma abordagem que escala melhor é organizar por <strong>domínio/feature</strong>. Exemplo: tudo relacionado a “Billing” fica próximo (requests, actions, policies, resources, etc.). Isso reduz a fricção para manter e evoluir partes específicas do sistema.</p>



<p>Você não precisa mudar tudo de uma vez. Dá para começar com um ou dois domínios e ir migrando aos poucos, sem reescrever o projeto inteiro.</p>



<h3 class="wp-block-heading">Estrutura tradicional do Laravel (por tipo)</h3>



<pre class="wp-block-preformatted">app/<br>├── Http/<br>│   ├── Controllers/<br>│   ├── Requests/<br>│   └── Resources/<br>├── Models/<br>├── Jobs/<br>├── Policies/<br>├── Services/</pre>



<p>Problema em projeto grande:<br>para entender <strong>Billing</strong>, você precisa abrir 6 pastas diferentes.</p>



<p>Estrutura por domínio / feature</p>



<p>app/<br>└── Domains/<br>└── Billing/<br>├── Http/<br>│ ├── Controllers/<br>│ ├── Requests/<br>│ └── Resources/<br>├── Actions/<br>├── Jobs/<br>├── Policies/<br>├── Models/<br>└── Services/</p>



<p>Ou até mais simples:</p>



<pre class="wp-block-preformatted">app/<br>└── Billing/<br>    ├── BillingController.php<br>    ├── CreateInvoice.php<br>    ├── Invoice.php<br>    ├── InvoicePolicy.php<br>    ├── SendInvoiceJob.php<br>    └── InvoiceResource.php</pre>



<p>O Laravel não se importa com a pasta, desde que o namespace esteja correto.</p>



<h2 class="wp-block-heading">Por que isso escala melhor?</h2>



<p>Porque quando alguém entra no projeto e precisa mexer em Billing:</p>



<ul class="wp-block-list">
<li>não precisa caçar arquivos espalhados</li>



<li>não quebra coisas de outros domínios</li>



<li>entende o fluxo mais rápido</li>



<li>reduz medo de alterar código</li>
</ul>



<p>Em projeto grande, isso faz <strong>muita diferença</strong>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Requests e validações como primeiro filtro</h2>



<p>Em projeto grande, dado ruim entrando vira bug caro. Centralizar validação em <strong>Form Requests</strong> mantém o controller limpo e torna regras de entrada explícitas.</p>



<p>Além disso, vale padronizar:</p>



<ul class="wp-block-list">
<li>mensagens de erro;</li>



<li>formatos de resposta (principalmente APIs);</li>



<li>validações compartilhadas (traits, rules customizadas).</li>
</ul>



<p>Quando a validação é consistente, o sistema vira mais previsível e o time para de reinventar a roda a cada endpoint.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Padronize respostas de API desde cedo</h2>



<p>Quando cada <a href="https://leonardonascimento.dev/tag/api/" type="post_tag" id="210">endpoint </a>responde de um jeito, cada client precisa de lógica diferente, e isso vira dívida técnica distribuída. Para projetos médios e grandes, uma camada consistente de resposta é obrigatória: Resources, transformers, ou uma padronização interna.</p>



<p>O ponto aqui não é “estética”. É operação. Quando algo quebra, você quer logs previsíveis, payload previsível, erros previsíveis. Isso reduz tempo de diagnóstico.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Regras de negócio: não misture persistência com decisão</h2>



<p>Um erro comum em Laravel é “decidir” coisas dentro de models e ao mesmo tempo persistir em todo lugar, sem fronteira clara. Em sistemas maiores, o ideal é separar:</p>



<ul class="wp-block-list">
<li><strong>Decisão / regra</strong> (o que pode ou não pode)</li>



<li><strong>Persistência</strong> (salvar, consultar)</li>



<li><strong>Orquestração</strong> (fluxo do caso de uso)</li>
</ul>



<p>Isso permite evoluir regra sem quebrar camada de persistência, e vice-versa. E facilita testar o que realmente importa: a regra.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Jobs, filas e idempotência não são detalhe</h2>



<p>Em projeto grande, você inevitavelmente vai para filas: e-mails, notificações, integrações, processamento pesado. O que quebra sistemas grandes não é “usar fila”. É usar fila sem cuidado com:</p>



<ul class="wp-block-list">
<li>idempotência (job rodar duas vezes sem duplicar efeito);</li>



<li>retries (quando deve tentar de novo e quando deve falhar);</li>



<li>timeouts;</li>



<li>dead letter / estratégia para falhas recorrentes;</li>



<li>logs por job.</li>
</ul>



<p>Se o seu projeto depende de integração externa, trate isso como cenário normal: o externo vai falhar. A fila é o lugar certo para absorver isso, desde que bem desenhado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Serviços externos: isole e trate como dependência instável</h2>



<p>Integrações externas deveriam estar em classes próprias (clients/adapters), com:</p>



<ul class="wp-block-list">
<li>timeout explícito;</li>



<li>tratamento de erro consistente;</li>



<li>retry controlado quando fizer sentido;</li>



<li>logs contextualizados.</li>
</ul>



<p>Evite espalhar <code>Http::post()</code> por todo lugar. Em projeto grande isso vira caos, porque não existe ponto único para ajustar comportamento (ex: mudar header, adicionar auth, alterar timeout).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Migrations, seeds e dados de referência bem cuidados</h2>



<p>Projeto grande normalmente tem muita migration. E migration desorganizada vira armadilha: ambientes quebram, dev novo não sobe projeto, staging fica inconsistente.</p>



<p>Boas práticas que ajudam:</p>



<ul class="wp-block-list">
<li>migrations com nomes claros;</li>



<li>dados de referência (enums/tabelas fixas) com seeders idempotentes;</li>



<li>evitar “seed que depende de estado manual”;</li>



<li>sempre testar “do zero” em ambiente limpo.</li>
</ul>



<p>Isso evita que o setup do projeto vire uma gincana.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Configuração: tudo em config e .env, nada hardcoded</h2>



<p>Quando cresce, o sistema precisa rodar em múltiplos ambientes e, muitas vezes, múltiplos clientes. Configuração hardcoded vira problema de deploy e vira risco de segurança.</p>



<p>Padronize:</p>



<ul class="wp-block-list">
<li><code>config/*.php</code> como fonte de configuração;</li>



<li><code>.env</code> apenas para valores variáveis;</li>



<li>nunca commitar senhas e keys;</li>



<li>e preferencialmente separar integrações por “config + service container”.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Observabilidade: logs estruturados desde o começo</h2>



<p>Em projetos grandes, o custo de “descobrir o que aconteceu” é alto. Sem logs bons você perde tempo, perde confiança e perde previsibilidade operacional.</p>



<p>O que vale padronizar:</p>



<ul class="wp-block-list">
<li>logs com contexto (tenant, user_id, request_id, correlation_id);</li>



<li>níveis corretos (info, warning, error);</li>



<li>logs de integrações e jobs;</li>



<li>e um formato consistente (para facilitar busca).</li>
</ul>



<p>Isso é o que transforma incidentes em diagnóstico rápido.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Testes: foque no que dá retorno real</h2>



<p>Não dá para testar tudo em projeto grande, e tentar fazê-lo costuma falhar. O que dá mais retorno é:</p>



<ul class="wp-block-list">
<li>testes de regras de negócio (unit/integration);</li>



<li>testes de fluxos críticos;</li>



<li>testes de contratos de API;</li>



<li>e testes de integração com serviços externos (com mocks ou ambientes controlados).</li>
</ul>



<p>Teste não é para “subir porcentagem”. É para reduzir risco onde mais dói.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Conclusão</h2>



<p>Projetos Laravel grandes não quebram porque Laravel é limitado. Eles quebram porque a base cresce sem estrutura, sem padrões e sem fronteiras claras entre responsabilidades.</p>



<p>Se você mantiver controllers finos, separar domínio/feature, isolar integrações, tratar filas com seriedade e padronizar validação/retorno/log, o projeto continua evoluindo sem virar um monstro. E o melhor: o time consegue manter velocidade sem sacrificar estabilidade.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/">Boas práticas para estruturar projetos em Laravel de médio e grande porte</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
