<?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>Laravel Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<atom:link href="https://leonardonascimento.dev/categoria/laravel/feed/" rel="self" type="application/rss+xml" />
	<link>https://leonardonascimento.dev/categoria/laravel/</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, 29 Jan 2026 16:54:19 +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>Laravel Archives - Leonardo Nascimento | Engenheiro de Software</title>
	<link>https://leonardonascimento.dev/categoria/laravel/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Arquitetura de uma API REST em Laravel preparada para produção</title>
		<link>https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/</link>
					<comments>https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Wed, 28 Jan 2026 22:44:00 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Dicas & Truques]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[teste]]></category>
		<category><![CDATA[api rest]]></category>
		<category><![CDATA[arquitetura de software]]></category>
		<category><![CDATA[autenticação api]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[ci/cd]]></category>
		<category><![CDATA[clean architecture]]></category>
		<category><![CDATA[desenvolvimento backend]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker compose]]></category>
		<category><![CDATA[documentação api]]></category>
		<category><![CDATA[engenharia de software]]></category>
		<category><![CDATA[github actions]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[laravel sanctum]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[projeto para portfólio]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[repository pattern]]></category>
		<category><![CDATA[service layer]]></category>
		<category><![CDATA[swagger]]></category>
		<category><![CDATA[testes automatizados]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2358</guid>

					<description><![CDATA[<p>Em processos seletivos técnicos, não basta entregar código funcional. Cada vez mais, empresas avaliam arquitetura, decisões técnicas, organização do projeto, automação e capacidade de escalar a solução. Este artigo detalha a arquitetura de uma API REST desenvolvida em Laravel para gerenciamento de tarefas, criada como parte de um teste técnico, mas estruturada como um projeto [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/">Arquitetura de uma API REST em Laravel preparada para produção</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Em processos seletivos técnicos, não basta entregar código funcional. Cada vez mais, empresas avaliam <strong>arquitetura, decisões técnicas, organização do projeto, automação e capacidade de escalar a solução</strong>.</p>



<p>Este artigo detalha a arquitetura de uma <strong><a href="https://leonardonascimento.dev/blog/como-monitorar-aplicacao-e-servidor-pelo-whatsapp-logs-erros-e-alertas/" type="post" id="2290">API REST</a> desenvolvida em Laravel para gerenciamento de tarefas</strong>, <a href="https://github.com/leonardop21/laravel-task" type="link" id="https://github.com/leonardop21/laravel-task" target="_blank" rel="noreferrer noopener nofollow">criada como parte de um teste técnico,</a> mas estruturada como um projeto <strong>pronto para produção</strong>, seguindo boas práticas amplamente utilizadas em ambientes corporativos.</p>



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



<h2 class="wp-block-heading" id="h-visao-geral-da-solucao">Visão geral da solução</h2>



<p>A aplicação consiste em uma <strong>API RESTful para gerenciamento de tarefas</strong>, com suporte a:</p>



<ul class="wp-block-list">
<li>Autenticação via Bearer Token (Laravel Sanctum)</li>



<li>CRUD completo de tarefas</li>



<li>Marcação de tarefas como concluídas</li>



<li>Cache de consultas com Redis</li>



<li>Banco de dados PostgreSQL</li>



<li>Documentação interativa via Swagger</li>



<li>Ambiente Dockerizado (dev, test e prod)</li>



<li>Testes automatizados</li>



<li>Pipeline de CI/CD com GitHub Actions</li>
</ul>



<p>O foco não foi apenas “fazer funcionar”, mas <strong>pensar a aplicação como um produto escalável e previsível</strong>.</p>



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



<h2 class="wp-block-heading" id="h-decisao-arquitetural-api-stateless-e-autenticacao">Decisão arquitetural: API stateless e autenticação</h2>



<p>A API foi construída como <strong>stateless</strong>, utilizando <strong>Bearer Token via Laravel Sanctum</strong>.</p>



<h3 class="wp-block-heading" id="h-beneficios-dessa-abordagem">Benefícios dessa abordagem:</h3>



<ul class="wp-block-list">
<li>Facilidade de integração com frontends (SPA, mobile, terceiros)</li>



<li>Independência de sessão</li>



<li>Escalabilidade horizontal</li>



<li>Compatibilidade com gateways, load balancers e proxies</li>
</ul>



<p>A autenticação é desacoplada do fluxo de negócio, o que facilita manutenção e evolução futura.</p>



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



<h2 class="wp-block-heading" id="h-postgresql-como-banco-principal">PostgreSQL como banco principal</h2>



<p>A escolha do <strong>PostgreSQL</strong> não foi aleatória. Ele é amplamente utilizado em ambientes corporativos por oferecer:</p>



<ul class="wp-block-list">
<li>Confiabilidade transacional</li>



<li>Suporte avançado a índices</li>



<li>Tipos de dados ricos</li>



<li>Excelente desempenho em cenários complexos</li>
</ul>



<p>Isso torna a aplicação preparada para crescer sem precisar trocar a base de dados no curto ou médio prazo.</p>



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



<h2 class="wp-block-heading" id="h-redis-como-camada-de-cache">Redis como camada de cache</h2>



<p>Para reduzir carga no banco e melhorar tempo de resposta, foi implementado <strong>cache com Redis</strong>, com TTL de 120 segundos nas consultas mais comuns.</p>



<h3 class="wp-block-heading" id="h-beneficios-diretos">Benefícios diretos:</h3>



<ul class="wp-block-list">
<li>Redução de queries repetitivas</li>



<li>Menor latência</li>



<li>Melhor desempenho sob carga</li>



<li>Escalabilidade em leitura</li>
</ul>



<p>Essa abordagem demonstra preocupação com <strong>performance real</strong>, não apenas com lógica funcional.</p>



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



<h2 class="wp-block-heading" id="h-arquitetura-limpa-repository-pattern-service-layer">Arquitetura limpa: Repository Pattern + Service Layer</h2>



<p><a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/" type="post" id="2348">A aplicação segue princípios de <strong>Clean Architecture</strong></a>, separando responsabilidades de forma clara:</p>



<ul class="wp-block-list">
<li><strong>Controllers</strong>: recebem requisições e retornam respostas</li>



<li><strong>Services</strong>: concentram regras de negócio</li>



<li><strong>Repositories</strong>: isolam o acesso a dados</li>



<li><strong>Models</strong>: representam as entidades</li>
</ul>



<h3 class="wp-block-heading" id="h-vantagens-dessa-separacao">Vantagens dessa separação:</h3>



<ul class="wp-block-list">
<li>Código mais legível</li>



<li>Facilidade de testes</li>



<li>Menor acoplamento</li>



<li>Evolução segura do domínio</li>
</ul>



<p>Essa estrutura é comum em times maduros e projetos de longo prazo.</p>



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



<h2 class="wp-block-heading" id="h-docker-como-base-do-ambiente">Docker como base do ambiente</h2>



<p>Toda a aplicação roda em <strong>Docker</strong>, com ambientes bem definidos:</p>



<h3 class="wp-block-heading" id="h-desenvolvimento">Desenvolvimento</h3>



<ul class="wp-block-list">
<li>Código em volume</li>



<li>Hot reload</li>



<li>PostgreSQL + Redis + Nginx</li>



<li>Testes executados automaticamente</li>
</ul>



<h3 class="wp-block-heading" id="h-producao">Produção</h3>



<ul class="wp-block-list">
<li>Build otimizado</li>



<li>Código embutido na imagem</li>



<li>Assets compilados no build</li>



<li>Sem dependência de volume</li>
</ul>



<p>Essa separação reduz o clássico problema de “funciona na minha máquina” e aproxima o ambiente local da produção.</p>



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



<h2 class="wp-block-heading" id="h-testes-automatizados-como-parte-do-fluxo">Testes automatizados como parte do fluxo</h2>



<p>A aplicação conta com <strong>testes unitários e de feature</strong>, executados de três formas:</p>



<ul class="wp-block-list">
<li>Localmente no ambiente dev</li>



<li>Isoladamente via Docker</li>



<li>Automaticamente no CI/CD</li>
</ul>



<p>Isso garante:</p>



<ul class="wp-block-list">
<li>Segurança para refatorações</li>



<li>Detecção precoce de bugs</li>



<li>Confiança na entrega contínua</li>
</ul>



<p>Testes não são tratados como opcional, mas como <strong>parte da arquitetura</strong>.</p>



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



<h2 class="wp-block-heading" id="h-ci-cd-com-github-actions">CI/CD com GitHub Actions</h2>



<p>Cada push ou pull request dispara um workflow que:</p>



<ol class="wp-block-list">
<li>Sobe toda a stack Docker (app, banco, cache)</li>



<li>Executa migrations</li>



<li>Roda a suíte completa de testes</li>



<li>Bloqueia o merge em caso de falha</li>
</ol>



<p>Esse processo simula um pipeline real de empresas que operam com <strong>entrega contínua e qualidade de código como requisito</strong>.</p>



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



<h2 class="wp-block-heading" id="h-documentacao-com-swagger">Documentação com Swagger</h2>



<p>A API possui <strong>documentação interativa via Swagger</strong>, acessível após subir a aplicação.</p>



<p>Isso permite:</p>



<ul class="wp-block-list">
<li>Testes manuais rápidos</li>



<li>Onboarding mais fácil</li>



<li>Comunicação clara entre backend e frontend</li>



<li>Uso por terceiros sem dependência de documentação externa</li>
</ul>



<p>Documentação é tratada como parte do produto, não como etapa posterior.</p>



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



<h2 class="wp-block-heading" id="h-beneficios-dessa-arquitetura-em-um-contexto-profissional">Benefícios dessa arquitetura em um contexto profissional</h2>



<p>Essa abordagem entrega vantagens claras em ambientes reais:</p>



<ul class="wp-block-list">
<li>Código organizado e previsível</li>



<li>Facilidade de manutenção</li>



<li>Escalabilidade técnica</li>



<li>Padronização de ambientes</li>



<li>Menor risco em deploys</li>



<li>Base sólida para crescimento</li>
</ul>



<p>Não se trata apenas de uma API de tarefas, mas de <strong>um modelo replicável para aplicações reais</strong>.</p>



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



<h2 class="wp-block-heading" id="h-o-que-esse-projeto-demonstra-tecnicamente">O que esse projeto demonstra tecnicamente</h2>



<p>Esse projeto evidencia competências como:</p>



<ul class="wp-block-list">
<li><a href="http://leonardonascimento.dev/categoria/laravel">Domínio de Laravel além do básico</a></li>



<li>Conhecimento de arquitetura backend</li>



<li>Uso consciente de cache e banco</li>



<li>Experiência com Docker e ambientes reais</li>



<li>Cultura de testes</li>



<li>Automação de CI/CD</li>



<li>Pensamento orientado a produto e escala</li>
</ul>



<p>São exatamente esses pontos que diferenciam um desenvolvedor <strong>pleno/sênior</strong> em processos seletivos.</p>



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



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



<p>Mais do que cumprir um teste técnico, o objetivo deste projeto foi demonstrar <strong>capacidade de pensar sistemas como um todo</strong>, indo além do CRUD simples.</p>



<p>Arquitetura, automação, testes e previsibilidade são o que tornam uma aplicação sustentável — e é isso que empresas buscam quando contratam profissionais para projetos de longo prazo.</p>



<p></p>



<p><a href="https://github.com/leonardop21/laravel-task" target="_blank" rel="noreferrer noopener nofollow">Link do teste prático</a></p>
<p>The post <a href="https://leonardonascimento.dev/blog/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/">Arquitetura de uma API REST em Laravel preparada para 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/arquitetura-de-uma-api-rest-em-laravel-preparada-para-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PHP além do CRUD: como escrever código que não vira problema em produção</title>
		<link>https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/</link>
					<comments>https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 11:05:00 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[arquitetura de software]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[boas práticas]]></category>
		<category><![CDATA[código limpo]]></category>
		<category><![CDATA[dto]]></category>
		<category><![CDATA[engenharia de software]]></category>
		<category><![CDATA[php avançado]]></category>
		<category><![CDATA[services layer]]></category>
		<category><![CDATA[sistemas em produção]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2348</guid>

					<description><![CDATA[<p>A maioria dos desenvolvedores PHP sabe fazer CRUD.Isso não te torna pleno. Muito menos sênior. O que diferencia um dev mais experiente não é o que ele sabe fazer, mas o que ele evita fazer. Vou te ensinar aqui um padrão prático, usado em projetos reais, que resolve três problemas clássicos: public function store(Request $request){if [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/">PHP além do CRUD: como escrever código que não vira problema 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 maioria dos desenvolvedores PHP sabe fazer CRUD.<br>Isso não te torna pleno. Muito menos sênior.</p>



<p>O que diferencia um dev mais experiente não é <em>o que ele sabe fazer</em>, mas <strong>o que ele evita fazer</strong>.</p>



<p>Vou te ensinar aqui <strong>um padrão prático</strong>, usado em projetos reais, que resolve três problemas clássicos:</p>



<ul class="wp-block-list">
<li>Controllers inchados</li>



<li>Regras de negócio espalhadas</li>



<li>Código impossível de testar ou evoluir</li>
</ul>



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



<p>public function store(Request $request)<br>{<br>if (!$request-&gt;email) {<br>return response()-&gt;json([&#8216;error&#8217; =&gt; &#8216;Email obrigatório&#8217;], 422);<br>}</p>



<pre class="wp-block-code"><code>$user = User::create(&#91;
    'name' =&gt; $request-&gt;name,
    'email' =&gt; $request-&gt;email,
]);

Mail::to($user-&gt;email)-&gt;send(new WelcomeMail($user));

Log::info('Usuário criado', &#91;'id' =&gt; $user-&gt;id]);

return response()-&gt;json($user);</code></pre>



<p>}</p>



<p>Funciona? Funciona.</p>



<p>É bom? Não.</p>



<p>Por quê?</p>



<ul class="wp-block-list">
<li>Controller decide regra de negócio</li>



<li>Controller cria usuário</li>



<li>Controller dispara e-mail</li>



<li>Controller registra log</li>
</ul>



<p>Isso <strong>acopla tudo</strong>.</p>



<h2 class="wp-block-heading" id="h-pensamento-pleno-senior-separar-responsabilidade">Pensamento pleno/sênior: separar responsabilidade</h2>



<p>Controller <strong>não decide regra</strong>.<br>Controller <strong>orquestra</strong>.</p>



<p>Vamos refatorar com um <strong>Service + DTO</strong>, padrão simples e poderoso.</p>



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



<h2 class="wp-block-heading" id="h-criando-um-dto-data-transfer-object">Criando um DTO (Data Transfer Object)</h2>



<p>Isso evita Request sendo usado como regra de negócio.</p>



<pre class="wp-block-code"><code>final class CreateUserDTO
{
    public function __construct(
        public readonly string $name,
        public readonly string $email,
    ) {}
}
</code></pre>



<p>Simples, explícito e tipado.</p>



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



<h2 class="wp-block-heading" id="h-criando-o-service-onde-a-regra-mora"> Criando o Service (onde a regra mora)</h2>



<pre class="wp-block-code"><code>final class CreateUserService
{
    public function execute(CreateUserDTO $dto): User
    {
        if (!filter_var($dto-&gt;email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Email inválido');
        }

        $user = User::create(&#91;
            'name' =&gt; $dto-&gt;name,
            'email' =&gt; $dto-&gt;email,
        ]);

        Mail::to($user-&gt;email)-&gt;send(new WelcomeMail($user));

        Log::info('Usuário criado', &#91;'id' =&gt; $user-&gt;id]);

        return $user;
    }
}
</code></pre>



<p>Agora sim:</p>



<ul class="wp-block-list">
<li>Regra centralizada</li>



<li>Código reutilizável</li>



<li>Fácil de testar</li>



<li>Fácil de evoluir</li>
</ul>



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



<h2 class="wp-block-heading" id="h-controller-limpo-como-deveria-ser"> Controller limpo (como deveria ser)</h2>



<pre class="wp-block-code"><code>public function store(Request $request, CreateUserService $service)
{
    $dto = new CreateUserDTO(
        name: $request-&gt;name,
        email: $request-&gt;email
    );

    $user = $service-&gt;execute($dto);

    return response()-&gt;json($user);
}
</code></pre>



<p>O controller:</p>



<ul class="wp-block-list">
<li>Recebe request</li>



<li>Constrói DTO</li>



<li>Chama serviço</li>



<li>Retorna resposta</li>
</ul>



<p>Nada além disso.</p>



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



<h2 class="wp-block-heading">O ganho real (que júnior não enxerga)</h2>



<h3 class="wp-block-heading" id="h-testabilidade">Testabilidade</h3>



<p>Agora você testa a regra <strong>sem framework</strong>:</p>



<pre class="wp-block-code"><code>public function test_user_creation()
{
    $service = new CreateUserService();

    $dto = new CreateUserDTO(
        name: 'Leo',
        email: 'leo@email.com'
    );

    $user = $service-&gt;execute($dto);

    $this-&gt;assertEquals('Leo', $user-&gt;name);
}
</code></pre>



<p>Sem Request.<br>Sem Controller.<br>Sem gambiarra.</p>



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



<h3 class="wp-block-heading" id="h-evolucao-sem-dor"> Evolução sem dor</h3>



<p>Amanhã você precisa:</p>



<ul class="wp-block-list">
<li>Enviar evento para fila</li>



<li>Criar usuário em sistema externo</li>



<li>Validar regra nova</li>
</ul>



<p>Você altera <strong>um lugar só</strong>.</p>



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



<h2 class="wp-block-heading">Mentalidade sênior (isso vale ouro)</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8221; Código que funciona não é código bom.mCódigo bom é o que aguenta mudança.&#8221; </p>
</blockquote>



<p>Pleno/sênior pensa assim:</p>



<ul class="wp-block-list">
<li>Onde essa regra deve morar?</li>



<li>O que vai mudar daqui 6 meses?</li>



<li>Quem vai dar manutenção nisso?</li>
</ul>



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



<h2 class="wp-block-heading">Erros clássicos que isso evita</h2>



<ul class="wp-block-list">
<li>Fat models</li>



<li>Controllers gigantes</li>



<li>Services que viram controllers</li>



<li>Regra duplicada</li>



<li>Código impossível de refatorar</li>
</ul>



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



<p>Esse tipo de abordagem <strong>não aparece em tutorial de YouTube</strong>, mas é exatamente o que mantém sistemas vivos em produção.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/">PHP além do CRUD: como escrever código que não vira problema 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/php-alem-do-crud-como-escrever-codigo-que-nao-vira-problema-em-producao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Deployment de Laravel no Cloud com CI/CD (GitHub Actions e GitLab CI)</title>
		<link>https://leonardonascimento.dev/blog/deployment-de-laravel-no-cloud-com-ci-cd-github-actions-e-gitlab-ci/</link>
					<comments>https://leonardonascimento.dev/blog/deployment-de-laravel-no-cloud-com-ci-cd-github-actions-e-gitlab-ci/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Tue, 13 Jan 2026 15:26:32 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Produção]]></category>
		<category><![CDATA[ci/cd]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[produção]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2295</guid>

					<description><![CDATA[<p>Deploy manual funciona até o dia em que deixa de funcionar. Enquanto o projeto é pequeno e o time é reduzido, subir código via SSH, rodar alguns comandos e torcer para dar certo parece aceitável. Em projetos reais, com mais gente mexendo, deploy frequente e produção rodando 24/7, isso vira risco operacional. CI/CD não é [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/deployment-de-laravel-no-cloud-com-ci-cd-github-actions-e-gitlab-ci/">Deployment de Laravel no Cloud com CI/CD (GitHub Actions e GitLab CI)</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Deploy manual funciona até o dia em que deixa de funcionar. Enquanto o projeto é pequeno e o time é reduzido, subir código via SSH, rodar alguns comandos e torcer para dar certo parece aceitável. Em projetos reais, com mais gente mexendo, deploy frequente e produção rodando 24/7, isso vira risco operacional.</p>



<p>CI/CD não é sobre velocidade. É sobre <strong>previsibilidade, repetibilidade e segurança</strong> no processo de entrega.</p>



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



<h2 class="wp-block-heading" id="h-o-que-ci-cd-realmente-resolve-em-projetos-laravel">O que CI/CD realmente resolve em projetos Laravel</h2>



<p>Em aplicações Laravel, o pipeline de deploy resolve três problemas clássicos:</p>



<ol class="wp-block-list">
<li><strong>Ambiente inconsistente</strong><br>O código roda local, mas quebra em produção porque algo foi esquecido ou executado fora de ordem.</li>



<li><strong>Deploys inseguros</strong><br>Código sobe sem testes, sem validação, sem rollback fácil.</li>



<li><strong>Processo dependente de pessoas</strong><br>“Só fulano sabe fazer deploy”. Quando ele não está, ninguém sobe nada.</li>
</ol>



<p>CI/CD elimina esses pontos ao transformar deploy em <strong>processo automatizado</strong>, não em ritual manual.</p>



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



<h2 class="wp-block-heading" id="h-conceito-basico-do-pipeline-independente-da-ferramenta">Conceito básico do pipeline (independente da ferramenta)</h2>



<p>Antes de falar de GitHub Actions ou GitLab CI, é importante entender o fluxo lógico. Um pipeline de Laravel bem definido costuma ter estas etapas:</p>



<ol class="wp-block-list">
<li><strong>Checkout do código</strong></li>



<li><strong>Instalação de dependências</strong></li>



<li><strong>Execução de testes</strong></li>



<li><strong>Build (quando aplicável)</strong></li>



<li><strong>Deploy</strong></li>



<li><strong>Pós-deploy (migrations, cache, filas)</strong></li>
</ol>



<p>Se qualquer etapa falhar, o deploy <strong>não acontece</strong>. Isso é uma proteção, não um obstáculo.</p>



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



<h2 class="wp-block-heading" id="h-estrutura-minima-de-um-deploy-laravel-saudavel">Estrutura mínima de um deploy Laravel saudável</h2>



<p>Independente de cloud ou CI, alguns princípios não mudam:</p>



<ul class="wp-block-list">
<li><code>composer install</code> sempre em modo produção</li>



<li><code>.env</code> nunca versionado</li>



<li><code>APP_ENV</code> e <code>APP_DEBUG</code> corretos</li>



<li>migrations rodando de forma controlada</li>



<li>cache/config/views limpos e recompilados</li>



<li>workers reiniciados corretamente</li>
</ul>



<p>Se isso não estiver automatizado, o risco é constante.</p>



<h2 class="wp-block-heading">Exemplo de pipeline com GitHub Actions</h2>



<p>Um pipeline simples, mas funcional, usando GitHub Actions:</p>



<pre class="wp-block-preformatted">name: Deploy Laravel<br><br>on:<br>  push:<br>    branches:<br>      - main<br><br>jobs:<br>  deploy:<br>    runs-on: ubuntu-latest<br><br>    steps:<br>      - name: Checkout<br>        uses: actions/checkout@v4<br><br>      - name: Setup PHP<br>        uses: shivammathur/setup-php@v2<br>        with:<br>          php-version: '8.2'<br>          extensions: mbstring, pdo, pdo_mysql<br><br>      - name: Install dependencies<br>        run: composer install --no-dev --optimize-autoloader<br><br>      - name: Run tests<br>        run: php artisan test<br><br>      - name: Deploy via SSH<br>        uses: appleboy/ssh-action@v1<br>        with:<br>          host: ${{ secrets.SERVER_HOST }}<br>          username: ${{ secrets.SERVER_USER }}<br>          key: ${{ secrets.SERVER_SSH_KEY }}<br>          script: |<br>            cd /var/www/app<br>            git pull origin main<br>            composer install --no-dev --optimize-autoloader<br>            php artisan migrate --force<br>            php artisan optimize<br>            php artisan queue:restart</pre>



<h2 class="wp-block-heading">Onde muita gente erra no deploy de Laravel</h2>



<h3 class="wp-block-heading">Rodar migration sem pensar em impacto</h3>



<p>Migration em produção pode travar tabela, gerar lentidão ou indisponibilidade. CI/CD não elimina isso. Ele apenas automatiza. Migration precisa ser escrita com consciência de produção.</p>



<h3 class="wp-block-heading">Cache mal tratado</h3>



<p>Não limpar/recriar cache de config e routes gera bugs difíceis de explicar. Cache antigo em produção é clássico.</p>



<h3 class="wp-block-heading">Workers esquecidos</h3>



<p>Deploy sobe código novo, mas workers continuam rodando código antigo. Resultado: comportamento inconsistente.</p>



<h3 class="wp-block-heading">Falta de rollback</h3>



<p>CI/CD sem rollback é metade da solução. Mesmo que seja manual, precisa existir um caminho claro para voltar.</p>



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



<h2 class="wp-block-heading">Estratégia simples de rollback</h2>



<p>Mesmo sem blue/green ou canary, dá para ter rollback básico:</p>



<ul class="wp-block-list">
<li>manter tags ou releases</li>



<li>usar <code>git checkout</code> para versão anterior</li>



<li>rodar <code>php artisan migrate:rollback</code> quando aplicável</li>



<li>reiniciar workers</li>
</ul>



<p>O importante é <strong>ter plano</strong>. Não improvisar sob pressão.</p>



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



<h2 class="wp-block-heading">CI/CD não substitui observabilidade</h2>



<p>Deploy automatizado reduz erro humano, mas não impede bugs. Por isso, CI/CD precisa andar junto com:</p>



<ul class="wp-block-list">
<li>monitoramento de erros</li>



<li>alertas pós-deploy</li>



<li>logs estruturados</li>



<li>métricas de saúde</li>
</ul>



<p>Deploy sem visibilidade é só um erro mais rápido.</p>



<p>CI/CD em projetos Laravel não é luxo nem modinha. É uma camada básica de segurança operacional. Ele garante que o código passe sempre pelo mesmo caminho, reduz risco humano e cria previsibilidade no processo de entrega.</p>



<p>Quando o deploy deixa de ser um evento tenso e vira algo rotineiro, o time ganha confiança para evoluir o sistema. E isso, no fim, é o que permite crescer sem quebrar tudo a cada release.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/deployment-de-laravel-no-cloud-com-ci-cd-github-actions-e-gitlab-ci/">Deployment de Laravel no Cloud com CI/CD (GitHub Actions e GitLab CI)</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/deployment-de-laravel-no-cloud-com-ci-cd-github-actions-e-gitlab-ci/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Erros comuns ao usar Redis em aplicações Laravel</title>
		<link>https://leonardonascimento.dev/blog/erros-comuns-ao-usar-redis-em-aplicacoes-laravel/</link>
					<comments>https://leonardonascimento.dev/blog/erros-comuns-ao-usar-redis-em-aplicacoes-laravel/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Sun, 11 Jan 2026 10:47:00 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[concorrência]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[produção]]></category>
		<category><![CDATA[redis]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2282</guid>

					<description><![CDATA[<p>Redis costuma entrar no projeto como sinônimo de performance. E, de fato, quando bem usado, ele resolve muita coisa. O problema é que em aplicações Laravel — principalmente quando começam a crescer — Redis também vira fonte de bugs difíceis, inconsistências e comportamentos estranhos quando é usado sem critério. A maioria desses problemas não vem [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/erros-comuns-ao-usar-redis-em-aplicacoes-laravel/">Erros comuns ao usar Redis em aplicações Laravel</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Redis costuma entrar no projeto como sinônimo de <a href="https://leonardonascimento.dev/tag/performance/" type="post_tag" id="209">performance</a>. E, de fato, quando bem usado, ele resolve muita coisa. O problema é que em aplicações Laravel — principalmente quando começam a crescer — Redis também vira fonte de bugs difíceis, inconsistências e comportamentos estranhos quando é usado sem critério.</p>



<p>A maioria desses problemas não vem do Redis em si, mas da forma como ele é integrado à aplicação. A seguir estão erros que aparecem com frequência em produção e o que aprender com eles.</p>



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



<p>Um dos erros mais comuns é <strong>tratar Redis como banco de dados principal</strong>. Redis é rápido, mas não é fonte de verdade. Dados em memória podem ser perdidos por restart, eviction ou falha de infraestrutura. Quando o sistema depende do Redis para manter estado crítico, qualquer limpeza vira incidente. Em aplicações maduras, Redis é sempre camada auxiliar; o banco relacional continua sendo a referência.</p>



<p>Outro problema recorrente é <strong><a href="https://leonardonascimento.dev/blog/quando-usar-cache-e-quando-ele-so-complica-o-sistema/" type="post" id="2251">cachear dados sem estratégia clara de invalidação</a></strong>. No começo, tudo parece funcionar: menos queries, respostas mais rápidas. Com o tempo, começam a aparecer dados desatualizados, comportamentos inconsistentes e bugs que “somem sozinhos”. Cache sem invalidação bem definida vira dívida técnica. Toda entrada em cache precisa ter resposta clara para três perguntas: quando expira, quem invalida e o que acontece se falhar.</p>



<p>Também é comum <strong>usar TTL genérico para tudo</strong>. Definir o mesmo tempo de expiração para dados completamente diferentes ignora o contexto. Dados quase estáticos podem ficar horas em cache; dados sensíveis a mudanças podem precisar de expiração curta ou invalidação ativa. TTL não é detalhe de configuração, é parte da regra de negócio.</p>



<p>Em projetos com filas e jobs, aparece bastante o erro de <strong>usar Redis sem pensar em concorrência</strong>. Dois workers acessando e alterando a mesma chave ao mesmo tempo geram condição de corrida. Incrementos, flags e estados intermediários precisam ser atômicos ou protegidos por lock. Ignorar isso funciona em teste, mas quebra sob carga.</p>



<p>Outro ponto crítico é <strong>usar Redis como solução para idempotência sem persistência complementar</strong>. Locks e flags em Redis ajudam, mas não garantem segurança total. Se o Redis reiniciar, o controle some. Para efeitos colaterais críticos (pagamento, notificação, integração externa), o controle final precisa estar no banco, com constraint ou registro explícito de processamento.</p>



<p>Muitos projetos também caem no erro de <strong>não separar namespaces ou prefixos de chave</strong>. Em aplicações maiores, isso gera colisão, dificuldade de debug e limpeza perigosa. Padronizar prefixos por domínio ou tipo de dado facilita manutenção e evita apagar cache errado.</p>



<p>Há ainda o uso excessivo de Redis para <strong>resolver problemas que não são de cache</strong>. Guardar lógica de negócio, estados complexos ou fluxos longos em memória costuma deixar o sistema frágil. Redis é ótimo para acelerar acesso, coordenar concorrência e compartilhar estado temporário, mas não substitui modelagem correta.</p>



<p>Outro erro que só aparece em produção é <strong>ignorar política de eviction e limites de memória</strong>. Quando a memória acaba, o Redis começa a remover chaves de acordo com a política configurada. Se isso não foi considerado no design, o sistema passa a perder cache crítico aleatoriamente, causando degradação inesperada. Monitorar uso de memória e entender eviction é obrigatório.</p>



<p>Também é comum <strong>não monitorar Redis como dependência crítica</strong>. Quando ele fica lento ou indisponível, a aplicação sofre. Sem métricas, alertas e logs específicos, o diagnóstico demora. Redis precisa estar no radar de observabilidade tanto quanto banco e API externa.</p>



<p>Por fim, um erro sutil: <strong>acoplar demais o código ao Redis</strong>. Quando a aplicação assume que Redis sempre está disponível, qualquer fallback vira difícil. Código mais saudável trata Redis como otimização opcional: se falhar, o sistema continua funcionando, mesmo que mais lento.</p>



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



<p>Redis é uma ferramenta poderosa, mas exige disciplina. <a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Em aplicações Laravel</a>, ele deve acelerar, proteger e coordenar — nunca sustentar a lógica principal do sistema. Quando tratado como camada auxiliar, com invalidação clara, controle de concorrência e observabilidade, ele entrega o que promete. Quando usado como atalho, cobra o preço em produção.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/erros-comuns-ao-usar-redis-em-aplicacoes-laravel/">Erros comuns ao usar Redis em aplicações Laravel</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/erros-comuns-ao-usar-redis-em-aplicacoes-laravel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Como evitar duplicidade de processamento em jobs</title>
		<link>https://leonardonascimento.dev/blog/como-evitar-duplicidade-de-processamento-em-jobs/</link>
					<comments>https://leonardonascimento.dev/blog/como-evitar-duplicidade-de-processamento-em-jobs/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Fri, 09 Jan 2026 16:28:42 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Produção]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2274</guid>

					<description><![CDATA[<p>Duplicidade em job é uma das coisas mais comuns (e mais perigosas) em produção. E não adianta lutar contra isso achando que “não vai acontecer”. Vai. Worker cai, timeout estoura, conexão oscila, retry acontece, o mesmo evento chega duas vezes, o deploy reinicia processo no meio… e pronto: job roda de novo. O objetivo não [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/como-evitar-duplicidade-de-processamento-em-jobs/">Como evitar duplicidade de processamento em jobs</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/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/" type="post" id="2271">Duplicidade em job </a>é uma das coisas mais comuns (e mais perigosas) em produção. E não adianta lutar contra isso achando que “não vai acontecer”. Vai. Worker cai, timeout estoura, conexão oscila, retry acontece, o mesmo evento chega duas vezes, o deploy reinicia processo no meio… e pronto: job roda de novo.</p>



<p>O objetivo não é “garantir que nunca execute duas vezes”. O objetivo é garantir que <strong>executar duas vezes não cause dano</strong>.</p>



<p>Abaixo estão as estratégias que realmente funcionam em projetos Laravel médios e grandes.</p>



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



<h2 class="wp-block-heading">1) Torne o job idempotente (regra número 1)</h2>



<p>Idempotência significa: <strong>rodar uma vez ou dez vezes dá o mesmo resultado final</strong>.</p>



<p>Isso é o que separa um job saudável de um job que vai te dar dor de cabeça.</p>



<p>Exemplos práticos:</p>



<ul class="wp-block-list">
<li>“enviar notificação”: marque como enviado e não envie novamente se já estiver enviado.</li>



<li>“gerar fatura”: use uma chave única e não crie duas faturas para o mesmo evento.</li>



<li>“sincronizar pedido”: atualize o registro existente em vez de criar um novo.</li>
</ul>



<p>Em termos práticos, idempotência quase sempre vira: <strong>checar estado antes de executar</strong> e <strong>persistir o estado depois</strong>.</p>



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



<h2 class="wp-block-heading">2) Use chave idempotente por evento (event_id / request_id)</h2>



<p>Toda vez que o seu sistema gera um job, ele deveria ter um identificador estável do evento.</p>



<p>Exemplo:</p>



<ul class="wp-block-list">
<li><code>event_id</code> do webhook recebido</li>



<li><code>message_id</code> da sua tabela</li>



<li><code>order_id</code> + <code>status</code> (depende do caso)</li>



<li>um UUID de “processamento” gerado quando o evento nasceu</li>
</ul>



<p>Aí você registra algo como:</p>



<ul class="wp-block-list">
<li>“event_id X já foi processado”</li>



<li>“order_id Y já teve ação Z executada”</li>
</ul>



<p>O melhor lugar para isso quase sempre é o banco, porque é fonte de verdade.</p>



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



<h2 class="wp-block-heading">3) Garanta unicidade no banco (constraints salvam sistemas)</h2>



<p>Se duplicidade causa duplicação de registro, não confie só em lógica de aplicação. Use o banco como proteção.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>índice unique em <code>invoice(event_id)</code></li>



<li>unique em <code>notifications(message_id, channel)</code></li>



<li>unique em <code>syncs(external_id)</code></li>
</ul>



<p>A aplicação tenta criar; se já existe, você trata e segue.</p>



<p>Isso é robusto porque:</p>



<ul class="wp-block-list">
<li>funciona mesmo com múltiplos workers</li>



<li>não depende de timing perfeito</li>



<li>reduz risco de corrida</li>
</ul>



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



<h2 class="wp-block-heading">4) Locks distribuídos (Redis) para evitar concorrência</h2>



<p>Locks são úteis quando você quer garantir que <strong>apenas um worker execute determinada seção crítica</strong> ao mesmo tempo.</p>



<p>Exemplo:</p>



<ul class="wp-block-list">
<li>processar um mesmo <code>order_id</code></li>



<li>consolidar um relatório</li>



<li>importar lote único</li>
</ul>



<p><a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Em Laravel</a>, dá pra fazer lock via cache (Redis):</p>



<ul class="wp-block-list">
<li>lock por chave: <code>lock:order:123</code></li>



<li>se não adquirir, outro worker já está executando</li>
</ul>



<p>Importante: lock não substitui idempotência. Ele reduz concorrência, mas não garante que um retry nunca vai rodar depois.</p>



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



<h2 class="wp-block-heading">5) Use “unique jobs” do Laravel (quando couber)</h2>



<p>Laravel tem suporte para jobs únicos (dependendo da versão/config), mas isso é mais útil para evitar enfileirar duplicado, não para evitar execução duplicada em qualquer cenário.</p>



<p>Use se:</p>



<ul class="wp-block-list">
<li>você quer impedir spam de job igual</li>



<li>o job é claramente único por chave</li>



<li>você entende as limitações (especialmente com retries e falhas)</li>
</ul>



<p>Mesmo com unique job, eu continuo recomendando idempotência + banco.</p>



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



<h2 class="wp-block-heading">6) Controle retries, timeout e backoff com critério</h2>



<p>Muita duplicidade aparece porque:</p>



<ul class="wp-block-list">
<li>job estoura timeout → worker mata → tenta de novo</li>



<li>job demora demais → você acha que falhou → reprocessa manualmente</li>



<li>dependência externa oscila → retries “na pancada”</li>
</ul>



<p>Ajuste bem:</p>



<ul class="wp-block-list">
<li><code>timeout</code> realista (nem baixo demais, nem infinito)</li>



<li><code>tries</code> coerente com o impacto</li>



<li><code>backoff</code> crescente para não sobrecarregar dependência externa</li>
</ul>



<p>O objetivo é evitar “tempestade de retries”.</p>



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



<h2 class="wp-block-heading">7) Separe “efeito colateral” do “estado principal”</h2>



<p>Quando duplicidade é perigosa, normalmente é porque o job faz um efeito colateral irreversível (ex: cobrar cartão, enviar WhatsApp, emitir nota). A abordagem mais segura é:</p>



<ol class="wp-block-list">
<li>persistir um estado interno (“pendente”, “processando”, “concluído”)</li>



<li>só então executar o efeito colateral</li>



<li>registrar resultado e contexto</li>
</ol>



<p>Isso cria trilha de auditoria e evita “executar no escuro”.</p>



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



<h2 class="wp-block-heading">8) Instrumente: trace por job e correlação</h2>



<p>Você só descobre duplicidade tarde se não tiver rastreabilidade.</p>



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



<ul class="wp-block-list">
<li><code>job_id</code>/<code>correlation_id</code> em logs</li>



<li>logar início/fim do job com chave do evento</li>



<li>métrica de “job duplicado evitado” (sim, isso ajuda muito)</li>
</ul>



<p>Quando dá problema, você quer saber: “por que rodou duas vezes?” em 2 minutos, não em 2 horas.</p>



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



<h2 class="wp-block-heading">Um padrão simples que funciona muito bem</h2>



<p>Se eu tivesse que resumir num padrão prático:</p>



<ul class="wp-block-list">
<li><strong>chave idempotente</strong> (event_id)</li>



<li><strong>tabela de processamento</strong> (<code>processed_events</code>) com unique</li>



<li><strong>lock Redis</strong> opcional em trechos críticos</li>



<li><strong>constraints no banco</strong> para proteger criação duplicada</li>



<li><strong>logs com correlação</strong></li>
</ul>



<p>Isso cobre 95% dos casos reais.</p>



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



<p><a href="https://leonardonascimento.dev/tag/producao/" type="post_tag" id="205">Em produção</a>, duplicidade em job não é exceção. É comportamento esperado do mundo real (retries, falhas, concorrência). O caminho profissional é aceitar isso e desenhar o job para ser seguro.</p>



<p>Job bom é o que pode rodar duas vezes sem te acordar de madrugada.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/como-evitar-duplicidade-de-processamento-em-jobs/">Como evitar duplicidade de processamento em jobs</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/como-evitar-duplicidade-de-processamento-em-jobs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</title>
		<link>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/</link>
					<comments>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Thu, 08 Jan 2026 14:22:46 +0000</pubDate>
				<category><![CDATA[Arquitetura]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[filas]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[mensageria]]></category>
		<category><![CDATA[processamento assíncrono]]></category>
		<category><![CDATA[produção]]></category>
		<category><![CDATA[redis]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=2271</guid>

					<description><![CDATA[<p>Fila resolve dor real: tirar do request o que não precisa estar ali. O problema é que muita gente usa fila como “remédio genérico” e acaba criando um sistema mais frágil, mais difícil de depurar e com risco de duplicidade. Jobs e processamento assíncrono são excelentes quando usados com critério. Quando usados por impulso, viram [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/">Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Fila resolve dor real: tirar do request o que não precisa estar ali. O problema é que muita gente usa fila como “remédio genérico” e acaba criando um sistema mais frágil, mais difícil de depurar e com risco de duplicidade.</p>



<p><a href="https://leonardonascimento.dev/categoria/laravel/" type="category" id="44">Jobs e processamento</a> assíncrono são excelentes quando usados com critério. Quando usados por impulso, viram fonte de incidentes.</p>



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



<h2 class="wp-block-heading">O que fila realmente te dá (e o que ela não dá)</h2>



<p>Fila te dá principalmente três coisas: desacoplamento do tempo de resposta, capacidade de absorver picos e reprocessamento controlado. Ela não te dá garantia de que algo vai rodar uma vez só, nem te livra de tratar falhas externas. Na verdade, ela te obriga a tratar isso.</p>



<p>Se você joga um processo para a fila sem pensar em idempotência, retries e observabilidade, você só mudou o problema de lugar.</p>



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



<h2 class="wp-block-heading">Quando usar jobs e filas</h2>



<h3 class="wp-block-heading">1) Tudo que não precisa bloquear o usuário</h3>



<p>Se o usuário não precisa do resultado imediato, isso já é um sinal forte de fila.</p>



<p>Exemplos comuns:</p>



<ul class="wp-block-list">
<li>envio de e-mail e notificações</li>



<li>geração de relatórios</li>



<li>criação de thumbnails / processamento de mídia</li>



<li>sincronização com sistemas externos</li>



<li>webhooks de saída (enviar eventos para terceiros)</li>
</ul>



<p>A regra prática: se o usuário já pode seguir o fluxo sem esperar, tire do request.</p>



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



<h3 class="wp-block-heading">2) Integrações externas e chamadas instáveis</h3>



<p><a href="https://leonardonascimento.dev/tag/api/" type="post_tag" id="210">API de terceiros falha</a>, oscila, responde lento. Fila é ótima para isso porque permite retries e isolamento.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>gateway de pagamento</li>



<li>WhatsApp / SMS</li>



<li>ERP e sistemas legados</li>



<li>qualquer HTTP externo</li>
</ul>



<p>Mas aqui entra o ponto crítico: fila não é desculpa para “tentar infinitamente”. Você precisa controlar tentativas e saber quando desistir.</p>



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



<h3 class="wp-block-heading">3) Processamentos pesados e previsíveis</h3>



<p><a href="https://leonardonascimento.dev/blog/boas-praticas-para-estruturar-projetos-em-laravel-de-medio-e-grande-porte/" type="post" id="2262">Tudo que consome</a> CPU, memória ou I/O e pode gerar timeout em request tende a ser melhor em job.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>exportar CSV grande</li>



<li>processar lote de dados</li>



<li>recalcular agregações</li>



<li>rodar rotinas de normalização/validação em massa</li>
</ul>



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



<h3 class="wp-block-heading">4) Fan-out (um evento dispara várias ações)</h3>



<p>Quando algo acontece e você precisa executar várias tarefas em sequência ou em paralelo, jobs ajudam a manter o sistema organizado.</p>



<p>Exemplo: “pedido pago” dispara:</p>



<ul class="wp-block-list">
<li>enviar confirmação</li>



<li>baixar estoque</li>



<li>emitir nota</li>



<li>notificar financeiro</li>



<li>gerar registro no CRM</li>
</ul>



<p>Se você faz tudo no request, vira um fluxo pesado e frágil. Com jobs, você separa responsabilidades.</p>



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



<h3 class="wp-block-heading">5) Absorver picos sem derrubar o sistema</h3>



<p>Fila é uma forma de “buffer”. Em vez de o sistema tentar processar tudo na hora e morrer, você coloca em fila e processa no ritmo que aguenta.</p>



<p>Isso é útil quando:</p>



<ul class="wp-block-list">
<li>picos são comuns</li>



<li>demanda varia muito</li>



<li>você precisa garantir estabilidade</li>
</ul>



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



<h2 class="wp-block-heading">Quando evitar jobs e filas</h2>



<h3 class="wp-block-heading">1) Quando você precisa de resposta imediata e consistente</h3>



<p>Se o usuário precisa saber na hora se deu certo, jogar em fila pode piorar a experiência.</p>



<p>Exemplos:</p>



<ul class="wp-block-list">
<li>login</li>



<li>criar pagamento e retornar confirmação</li>



<li>reservar algo que não pode duplicar</li>



<li>operações transacionais críticas</li>
</ul>



<p>Você até pode usar job para efeitos colaterais, mas a decisão central precisa ser síncrona.</p>



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



<h3 class="wp-block-heading">2) Quando a operação é simples e rápida</h3>



<p>Às vezes a operação leva 20ms e você coloca na fila “por padrão”. Isso adiciona:</p>



<ul class="wp-block-list">
<li>complexidade</li>



<li>delay</li>



<li>necessidade de monitoramento</li>



<li>risco de falha assíncrona</li>
</ul>



<p>Fila não pode ser usada como padrão para tudo. Senão você cria um sistema cheio de jobs pequenos e difíceis de rastrear.</p>



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



<h3 class="wp-block-heading">3) Quando você não tem observabilidade</h3>



<p>Fila sem visibilidade vira caixa-preta.</p>



<p>Se você não tem:</p>



<ul class="wp-block-list">
<li>logs por job</li>



<li>métricas de falha</li>



<li>alertas de backlog</li>



<li>dead-letter ou estratégia de falha</li>
</ul>



<p>você vai descobrir problemas tarde demais. Nesse cenário, manter síncrono pode ser mais seguro até organizar a casa.</p>



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



<h3 class="wp-block-heading">4) Quando você não consegue garantir idempotência</h3>



<p>Jobs podem rodar duas vezes. Isso é normal: retry, timeouts, quedas de worker, reentregas. Se o job não é idempotente, você corre risco de:</p>



<ul class="wp-block-list">
<li>cobrança duplicada</li>



<li>disparo duplicado</li>



<li>registro duplicado</li>



<li>integração duplicada</li>
</ul>



<p>Se não dá para tornar idempotente, trate o caso com mais cuidado. Às vezes o certo é manter a operação central síncrona e colocar apenas efeitos colaterais na fila.</p>



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



<h2 class="wp-block-heading">O ponto que derruba sistemas: duplicidade</h2>



<p>Em produção, o seu job vai rodar duas vezes em algum momento. Não é “se”, é “quando”. Por isso, projetos maduros tratam idempotência como requisito.</p>



<p>Algumas abordagens comuns:</p>



<ul class="wp-block-list">
<li>chave idempotente por evento (event_id / request_id)</li>



<li>lock distribuído (Redis)</li>



<li>uniqueness controlada (Laravel unique jobs quando aplicável)</li>



<li>constraints no banco (único onde fizer sentido)</li>
</ul>



<p>Não é uma bala de prata, mas é obrigatório ter uma estratégia.</p>



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



<h2 class="wp-block-heading">Filas também precisam de limites</h2>



<p>Jobs não podem tentar para sempre. Você precisa definir:</p>



<ul class="wp-block-list">
<li>número de tentativas</li>



<li>backoff entre tentativas</li>



<li>timeout</li>



<li>comportamento ao falhar (alerta, dead letter, reprocessamento manual)</li>
</ul>



<p>E precisa aceitar que algumas coisas falham. O sistema não pode entrar em loop eterno tentando recuperar erro externo.</p>



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



<h2 class="wp-block-heading">Sinais de que você deve ir para fila</h2>



<p>Se você está em dúvida, aqui vão sinais bem práticos:</p>



<ul class="wp-block-list">
<li>requests começando a estourar timeout</li>



<li>picos derrubando a API</li>



<li>integrações externas travando fluxos principais</li>



<li>usuários esperando por coisas que não precisam esperar</li>



<li>o mesmo fluxo acumulando responsabilidades demais</li>
</ul>



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



<p>Jobs e filas são uma das melhores ferramentas para dar escala e estabilidade em sistemas Laravel, mas elas exigem maturidade. Quando bem usadas, melhoram performance, isolam falhas e deixam o sistema mais previsível. Quando usadas sem critério, viram um sistema difícil de operar, cheio de jobs duplicados e incidentes intermitentes.</p>



<p>Fila não é atalho. É arquitetura.</p>
<p>The post <a href="https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/">Laravel: Jobs, filas e processamento assíncrono: quando usar e quando evitar</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/laravel-jobs-filas-e-processamento-assincrono-quando-usar-e-quando-evitar/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>
		<item>
		<title>Hospede seu site em um servidor Cloud por menos de R$ 11 Mês</title>
		<link>https://leonardonascimento.dev/blog/hospede-seu-site-em-um-servidor-cloud-por-menos-de-r-11-mes/</link>
					<comments>https://leonardonascimento.dev/blog/hospede-seu-site-em-um-servidor-cloud-por-menos-de-r-11-mes/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Sun, 20 Oct 2024 23:55:15 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[acesso remoto]]></category>
		<category><![CDATA[acesso SSH]]></category>
		<category><![CDATA[anti-spam]]></category>
		<category><![CDATA[aplicações]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[balanceador de carga]]></category>
		<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[como configurar um servidor web]]></category>
		<category><![CDATA[compartilhada]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[consumo]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[CronJob]]></category>
		<category><![CDATA[disco]]></category>
		<category><![CDATA[downgrade]]></category>
		<category><![CDATA[e-mails]]></category>
		<category><![CDATA[editor de arquivos]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[FTP]]></category>
		<category><![CDATA[gerenciador de banco de dados]]></category>
		<category><![CDATA[GitLab]]></category>
		<category><![CDATA[hospedagem]]></category>
		<category><![CDATA[hospedagem boa e barata 2023]]></category>
		<category><![CDATA[hospedagem laravel barata]]></category>
		<category><![CDATA[hospedagem wordress barata]]></category>
		<category><![CDATA[Hostoo]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[Linode]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[melhor hospedagem de 2022]]></category>
		<category><![CDATA[melhor hospedagem de 2023]]></category>
		<category><![CDATA[migração]]></category>
		<category><![CDATA[onde hospedar meu site]]></category>
		<category><![CDATA[painel de controle]]></category>
		<category><![CDATA[PHPMyAdmin]]></category>
		<category><![CDATA[qual o melhor lugar pra hospedar site]]></category>
		<category><![CDATA[RAM]]></category>
		<category><![CDATA[recarga]]></category>
		<category><![CDATA[restauração]]></category>
		<category><![CDATA[revenda]]></category>
		<category><![CDATA[servidor]]></category>
		<category><![CDATA[servidor barato]]></category>
		<category><![CDATA[servidor cloud barato]]></category>
		<category><![CDATA[servidor php barato]]></category>
		<category><![CDATA[servidor vps barato]]></category>
		<category><![CDATA[servidor web configurado]]></category>
		<category><![CDATA[servidor web configurável]]></category>
		<category><![CDATA[servidor wordpress barato]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[suporte]]></category>
		<category><![CDATA[tecnologia]]></category>
		<category><![CDATA[tráfego]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[valor]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=251</guid>

					<description><![CDATA[<p>Não tem conhecimento de como configurar um servidor Cloud ou simplesmente não quer ter dores de cabeça para gerenciar um Servidor? Calma que...</p>
<p>The post <a href="https://leonardonascimento.dev/blog/hospede-seu-site-em-um-servidor-cloud-por-menos-de-r-11-mes/">Hospede seu site em um servidor Cloud por menos de R$ 11 Mês</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Seja para quem é iniciante ou dinossauro na área de tecnologia, sempre fica aquela dúvida, qual o melhor e mais barato serviço de hospedagem atualmente? Hospedagem Cloud ou compartilhada? (Compartilhada não quero mais nem de graça). Se você já tem um certo conhecimento, claro que compensa muito mais <a rel="noreferrer noopener" href="http://bit.ly/3gfVBud" data-type="URL" data-id="http://bit.ly/3gfVBud" target="_blank">configurar seu próprio servidor</a> e alocar seus clientes, a desvantagem é que você fica responsável por praticamente tudo, configurar gerenciador de hospedagem, e-mails, quedas de serviços entre outros, neste caso, recomendo a <a rel="noreferrer noopener" href="http://bit.ly/3gfVBud" data-type="URL" data-id="http://bit.ly/3gfVBud" target="_blank">Linode, sem medo de errar.</a></p>



<p>Porém, todavia, entretanto, contudo, se você não tem um grande conhecimento em gerenciamento de hospedagens, ou simplesmente não quer se incomodar em prestar suporte para o seu cliente, <a href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank" rel="noreferrer noopener">poderá muito bem optar por um Cloud 100% configurado com:</a></p>



<ul class="wp-block-list">
<li>Servidor Cloud individual (Apenas o seu site hospedado no Cloud)</li>



<li>E-mails ilimitados</li>



<li>SSL grátis</li>



<li>Firewall</li>



<li>Tráfego ilimitado</li>



<li>Banco de dados ilimitados</li>



<li>Backup grátis</li>



<li>Acesso SSH</li>



<li>Software anti-spam para e-mails</li>



<li>Upgrade/Downgrade de plano direto pelo painel, sem precisar abrir ticket e sem downtime</li>



<li>Suporte grátis</li>



<li>Instalações de aplicações com poucos cliques</li>



<li>Revenda de  hospedagem</li>



<li>Plugin de cache (WordPress)</li>



<li>Editor de arquivos</li>



<li>FTP</li>



<li>Deploy pelo GitLab em breve Github e Bitbucket</li>



<li>Restauração de backup em poucos cliques</li>



<li>Gerenciador de banco de dados (PHPMYADMIN)</li>



<li>Acesso remoto ao banco de dados</li>



<li>Escolher entre Mysql e PostgreSQL</li>



<li>Balanceador de carga</li>



<li>Escolher versões do PHP (5.4 até &gt;= 8.0) </li>



<li>CronJob direto pelo painel</li>



<li>Logs de erro do PHP e do servidor</li>



<li>Migração dos seus dados gratuitamente (Consulte)</li>



<li>Hospedagem individualizada, sem compartilhamento de CPU e memória com outros sites</li>



<li>Sem fidelidade (cancele quando quiser)</li>



<li><strong>A partir de R$ 10,90</strong></li>
</ul>



<p>Lembrando que o valor de R$ 10,90 é a configuração inicial, se você precisar de mais poder de processamento, poderá efetuar upgrade da sua instância, com valores adicionais.</p>



<p><strong>Sem surpresas na conta</strong></p>



<p>Você está no controle da sua hospedagem, no painel de controle, é possível verificar uma estimativa de quantos créditos você ainda possuí e quanto tempo ele irá durar. </p>



<p>Você pode optar por deixar a recarga automática através de cartão de crédito, também é possível inserir créditos através de boleto bancário, Pix ou mercado pago.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="324" height="96" src="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-1.png" alt="" class="wp-image-253" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-1.png 324w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-1-300x89.png 300w" sizes="(max-width: 324px) 100vw, 324px" /><figcaption class="wp-element-caption">Estimativa de valor e duração do crédito em dias</figcaption></figure>



<p><strong>Você no controle</strong></p>



<p>Com a <a rel="noreferrer noopener" href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank">hostoo</a> você está no controle e não precisa ser expert em servidores, é possível efetuar upgrade e downgrade de servidor com poucos cliques e sem deixar o seu site offline. Instale e configure aplicações em poucos cliques. Gosta do WordPress? Plugin de cache gratuito para acelerar ainda mais o carregamento do seu site.</p>



<p>No print abaixo, podemos notar o domínio do site, versão do PHP, SSL ativo, detalhes do plano, detalhes de consumo de CPU, RAM, disco e outras configurações da hospedagem.</p>



<figure class="wp-block-image size-large"><a href="https://bit.ly/3f83PxE"><img fetchpriority="high" decoding="async" width="1024" height="479" src="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-2-1024x479.png" alt="" class="wp-image-254" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-2-1024x479.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-2-300x140.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-2-768x359.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-2.png 1362w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption"><a href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank" rel="noreferrer noopener">PAINEL DE CONTROLE HOSTOO</a></figcaption></figure>



<p><strong>Precisa de mais?</strong></p>



<p>Além de ter servidores nos Estados Unidos, também é possível hospedar seus sites em clouds aqui no Brasil, claro, por um valor adicional. Com a<a rel="noreferrer noopener" href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank"> Hostoo você pode fazer upgrade de plano facilmente</a>. Suponhamos que durante o dia, você teve visitas atípicas em seu website, resultando em um consumo máximo de CPU e RAM, e agora o que fazer? Em poucos cliques, você pode efetuar upgrade do seu plano, contratando um cloud melhor, pagando por hora utilizada, e posteriormente, retornar ao plano original, você está 100% no controle.</p>



<p><strong>Suporte que não te deixa 48h esperando</strong></p>



<p>Estou com a <a rel="noreferrer noopener" href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank">Hostoo há mais de 1 ano</a> e diferente de outros serviços de hospedagem, o suporte é muito rápido e definitivamente resolve seus problemas. Até o momento, precisei abrir apenas 1 ticket de site fora do ar, onde ficou constatado que o problema não era na hospedagem e sim no servidor dns que eu estava utilizando como proxy, o outro ticket? Foi aberto pela própria empresa, quando me deparei com um erro 500 no painel de hospedagem. Tempo da primeira resposta &lt; 22 minutos.</p>



<figure class="wp-block-image size-large"><a href="https://bit.ly/3f83PxE" target="_blank" rel="noreferrer noopener"><img decoding="async" width="1024" height="305" src="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-3-1024x305.png" alt="" class="wp-image-258" srcset="https://leonardonascimento.dev/wp-content/uploads/2022/11/image-3-1024x305.png 1024w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-3-300x89.png 300w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-3-768x229.png 768w, https://leonardonascimento.dev/wp-content/uploads/2022/11/image-3.png 1364w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption"><a href="https://bit.ly/3f83PxE" data-type="URL" data-id="https://bit.ly/3f83PxE" target="_blank" rel="noreferrer noopener">Painel de suporte Hostoo</a></figcaption></figure>



<p>Sem dúvidas, foi um grande achado que estou compartilhando com você! <a href="https://bit.ly/3f83PxE" target="_blank" rel="noreferrer noopener">https://hostoo.io</a></p>
<p>The post <a href="https://leonardonascimento.dev/blog/hospede-seu-site-em-um-servidor-cloud-por-menos-de-r-11-mes/">Hospede seu site em um servidor Cloud por menos de R$ 11 Mês</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/hospede-seu-site-em-um-servidor-cloud-por-menos-de-r-11-mes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Como criar um repositório no Laravel</title>
		<link>https://leonardonascimento.dev/blog/como-criar-um-repositorio-no-laravel/</link>
					<comments>https://leonardonascimento.dev/blog/como-criar-um-repositorio-no-laravel/#respond</comments>
		
		<dc:creator><![CDATA[Leonardo]]></dc:creator>
		<pubDate>Sun, 20 Oct 2024 23:55:14 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<guid isPermaLink="false">https://leonardonascimento.dev/?p=278</guid>

					<description><![CDATA[<p>O Laravel é um framework de PHP populado que facilita a criação de aplicativos web. Um dos recursos úteis do Laravel é o uso de repositórios para gerenciar o acesso a dados em seu aplicativo. Um repositório é uma camada de abstração que separa o acesso a dados de sua lógica de negócios. Isso significa [&#8230;]</p>
<p>The post <a href="https://leonardonascimento.dev/blog/como-criar-um-repositorio-no-laravel/">Como criar um repositório no Laravel</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>O Laravel é um framework de PHP populado que facilita a criação de aplicativos web. Um dos recursos úteis do Laravel é o uso de repositórios para gerenciar o acesso a dados em seu aplicativo.</p>



<p>Um repositório é uma camada de abstração que separa o acesso a dados de sua lógica de negócios. Isso significa que, em vez de escrever código para acessar diretamente o banco de dados em suas classes de modelo, você pode usar métodos do repositório para realizar operações de banco de dados. Isso pode tornar o seu código mais legível e facilita a manutenção.</p>



<p>Para criar um repositório no Laravel, siga estes passos:</p>



<ol class="wp-block-list">
<li>Crie uma nova interface de repositório em <code>app/Repositories</code>. Esta interface deve conter métodos para as operações de banco de dados que você deseja realizar (por exemplo, obter todos os registros, obter um registro pelo ID, salvar um novo registro, etc.).</li>



<li>Crie uma nova classe de repositório que implemente a interface de repositório criada no passo 1. Esta classe deve conter a lógica para realizar as operações de banco de dados usando a classe de modelo correspondente do Laravel.</li>



<li>Adicione o repositório criado ao container de injeção de dependência do Laravel em <code>app/Providers/AppServiceProvider.php</code>. Isso permitirá que o Laravel crie uma instância do repositório quando for necessário.</li>



<li>Em sua classe de modelo, adicione uma propriedade privada para a instância do repositório e um construtor que aceite uma instância do repositório como argumento. Isso permitirá que você use o repositório em sua classe de modelo para realizar operações de banco de dados.</li>
</ol>



<pre class="wp-block-code"><code>&lt;?php

namespace App\Repositories;

interface PostRepositoryInterface
{
  public function getAll();
  public function findById($id);
  public function save($data);
  public function update($id, $data);
  public function delete($id);
}

</code></pre>



<pre class="wp-block-code"><code>&lt;?php

namespace App\Repositories;

use App\Models\Post;

class PostRepository implements PostRepositoryInterface
{
  protected $model;

  public function __construct(Post $model)
  {
    $this->model = $model;
</code></pre>
<p>The post <a href="https://leonardonascimento.dev/blog/como-criar-um-repositorio-no-laravel/">Como criar um repositório no Laravel</a> appeared first on <a href="https://leonardonascimento.dev">Leonardo Nascimento | Engenheiro de Software</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://leonardonascimento.dev/blog/como-criar-um-repositorio-no-laravel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
