<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tomás Alegre Sepúlveda</title>
    <description>The latest articles on Forem by Tomás Alegre Sepúlveda (@alpha018).</description>
    <link>https://forem.com/alpha018</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2032745%2F7d24f6ba-283c-402f-826d-e73a9318f3a7.jpeg</url>
      <title>Forem: Tomás Alegre Sepúlveda</title>
      <link>https://forem.com/alpha018</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alpha018"/>
    <language>en</language>
    <item>
      <title>🔬 NestJS vs Go: Performance Benchmark (Do you really need to migrate?)</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Tue, 10 Mar 2026 02:00:34 +0000</pubDate>
      <link>https://forem.com/alpha018/nestjs-vs-go-performance-benchmark-do-you-really-need-to-migrate-26eb</link>
      <guid>https://forem.com/alpha018/nestjs-vs-go-performance-benchmark-do-you-really-need-to-migrate-26eb</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/alpha018/nestjs-vs-go-benchmark-de-rendimiento-realmente-necesitas-migrar-4cd0"&gt;🇪🇸 Lee este post en Español&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello everyone. I recently conducted an exhaustive benchmark to answer a classic question in backend teams: &lt;strong&gt;does it make sense to migrate to Go, or is NestJS enough?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no magic answer, but data helps decide. Here is a summary of the most important findings.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ The Scenario
&lt;/h2&gt;

&lt;p&gt;I compared two typical architectures running in Docker on the same machine (M4 Pro):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;NestJS (Node 22) + Prisma v6&lt;/strong&gt; (Productivity approach)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Go (1.24) + GORM&lt;/strong&gt; (Performance approach)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both connected to &lt;strong&gt;PostgreSQL 15&lt;/strong&gt; and subjected to stress tests (gRPC and HTTP) simulating a real environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Methodology: What did we measure?
&lt;/h2&gt;

&lt;p&gt;To truly understand the differences, I divided the tests into two key scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Small Data (1x1 Insert):&lt;/strong&gt;&lt;br&gt;
Simulates typical transactional traffic of a REST/gRPC API. We receive an object, validate it, and save it. Here we measure the framework's base latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large Data (Batch Insert of 1000 elements):&lt;/strong&gt;&lt;br&gt;
Simulates bulk load processes, ETLs, or event ingestion. We send arrays of 1000 objects that must be deserialized, validated, and saved in a single transaction. This is where &lt;strong&gt;CPU and Garbage Collector&lt;/strong&gt; suffer the most.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📊 The Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Small Data: The Surprise
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;low load or unit insert&lt;/strong&gt; scenarios, the difference was minimal. Go obtained a latency improvement of just &lt;strong&gt;~10%&lt;/strong&gt; over NestJS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; For standard CRUD operations, NestJS is incredibly efficient, and the performance difference rarely justifies losing TypeScript's productivity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Large Data: The Breaking Point
&lt;/h3&gt;

&lt;p&gt;The story changes drastically when processing massive batches (arrays of 1000 elements) under high concurrency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario: 100 RPS constant (Bulk Inserts)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Real Throughput&lt;/th&gt;
&lt;th&gt;P95 Latency&lt;/th&gt;
&lt;th&gt;Success Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go gRPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;85 RPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;71.88 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NestJS gRPC&lt;/td&gt;
&lt;td&gt;78 RPS&lt;/td&gt;
&lt;td&gt;98.44 ms&lt;/td&gt;
&lt;td&gt;~85%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What happened here?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Serialization:&lt;/strong&gt; Node.js (V8) has a higher cost when serializing/deserializing large volumes of JSON compared to Go Structs and Protobuf.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Connection Pool:&lt;/strong&gt; Under extreme pressure, the Prisma connection pool started to saturate (&lt;code&gt;P2024&lt;/code&gt; errors), causing &lt;strong&gt;NestJS to lose ~15% of requests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Stability:&lt;/strong&gt; Go maintained 100% success and more predictable latencies, thanks to its goroutine management and a more efficient GC for this type of load.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚖️ Conclusion: When to use which?
&lt;/h2&gt;

&lt;p&gt;Based on the data, here is my pragmatic recommendation:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Stay with NestJS if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  You are building an MVP or validating a product.&lt;/li&gt;
&lt;li&gt;  Your team already knows TypeScript and you value development speed.&lt;/li&gt;
&lt;li&gt;  The load is moderate (&amp;lt; 300 RPS) and standard CRUD operations (Small Data).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;BFF (Backend for Frontend):&lt;/strong&gt; If you only need to orchestrate calls to a few services and the serialization load is low.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🚀 Migrate to Go if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Complex BFF:&lt;/strong&gt; If your BFF needs to call many microservices, add heavy logic, serialize large volumes of data, and perform massive fan-out, Go will handle concurrency much better.&lt;/li&gt;
&lt;li&gt;  Your system constantly performs massive &lt;strong&gt;Bulk Operations / ETL&lt;/strong&gt; (Large Data).&lt;/li&gt;
&lt;li&gt;  You need to handle thousands of concurrent connections (e.g., Gateways, massive Websockets).&lt;/li&gt;
&lt;li&gt;  You have very strict latency SLAs where Node's Garbage Collector spikes are unacceptable.&lt;/li&gt;
&lt;li&gt;  Infrastructure is expensive and you need to squeeze every CPU cycle.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📖 Read the full analysis
&lt;/h2&gt;

&lt;p&gt;This post is a summary. The detailed analysis (with all tables, charts, hardware configuration, and error analysis) is &lt;strong&gt;public and free&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://buymeacoffee.com/alpha018/nestjs-vs-go-what-data-says-use" rel="noopener noreferrer"&gt;Read the full article on Buy Me a Coffee&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;&lt;a href="https://github.com/Alpha018/grpc-http-performance-lab" rel="noopener noreferrer"&gt;View code on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;💌 &lt;strong&gt;Special Acknowledgments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To a girl who, without knowing it, pushed me to keep creating and programming in my free time. To the one who was once my spark: for "YLP", with gratitude... and with scars that also teach.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you find this analysis useful, any feedback is welcome!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>nestjs</category>
      <category>performance</category>
    </item>
    <item>
      <title>🔬 NestJS vs Go: Benchmark de Rendimiento (¿Realmente necesitas migrar?)</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Mon, 09 Mar 2026 00:17:36 +0000</pubDate>
      <link>https://forem.com/alpha018/nestjs-vs-go-benchmark-de-rendimiento-realmente-necesitas-migrar-4cd0</link>
      <guid>https://forem.com/alpha018/nestjs-vs-go-benchmark-de-rendimiento-realmente-necesitas-migrar-4cd0</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/alpha018/nestjs-vs-go-performance-benchmark-do-you-really-need-to-migrate-26eb"&gt;🇺🇸 Read this post in English&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hola a todos. Recientemente realicé un benchmark exhaustivo para responder una pregunta clásica en equipos de backend: &lt;strong&gt;¿tiene sentido migrar a Go, o alcanza con NestJS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No hay respuesta mágica, pero los datos ayudan a decidir. Aquí les dejo un resumen de los hallazgos más importantes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ El Escenario
&lt;/h2&gt;

&lt;p&gt;Comparé dos arquitecturas típicas corriendo en Docker sobre la misma máquina (M4 Pro):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;NestJS (Node 22) + Prisma v6&lt;/strong&gt; (Enfoque productividad)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Go (1.24) + GORM&lt;/strong&gt; (Enfoque rendimiento)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ambos conectados a &lt;strong&gt;PostgreSQL 15&lt;/strong&gt; y sometidos a pruebas de estrés (gRPC y HTTP) simulando un entorno real.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Metodología: ¿Qué medimos?
&lt;/h2&gt;

&lt;p&gt;Para entender realmente las diferencias, dividí las pruebas en dos escenarios clave:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Small Data (1x1 Insert):&lt;/strong&gt;&lt;br&gt;
Simula el tráfico transaccional típico de una API REST/gRPC. Recibimos un objeto, lo validamos y lo guardamos. Aquí medimos la latencia base del framework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large Data (Batch Insert de 1000 elementos):&lt;/strong&gt;&lt;br&gt;
Simula procesos de carga masiva, ETLs o ingestión de eventos. Enviamos arrays de 1000 objetos que deben ser deserializados, validados y guardados en una sola transacción. Aquí es donde &lt;strong&gt;la CPU y el Garbage Collector&lt;/strong&gt; sufren más.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📊 Los Resultados
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Small Data: La sorpresa
&lt;/h3&gt;

&lt;p&gt;En escenarios de &lt;strong&gt;baja carga o inserciones unitarias&lt;/strong&gt;, la diferencia fue mínima. Go obtuvo una mejora de latencia de apenas un &lt;strong&gt;~10%&lt;/strong&gt; sobre NestJS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Conclusión:&lt;/strong&gt; Para operaciones CRUD estándar, NestJS es increíblemente eficiente y la diferencia de rendimiento rara vez justifica perder la productividad de TypeScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Large Data: El punto de quiebre
&lt;/h3&gt;

&lt;p&gt;La historia cambia drásticamente cuando procesamos lotes masivos (arrays de 1000 elementos) bajo alta concurrencia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Escenario: 100 RPS constantes (Bulk Inserts)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Servicio&lt;/th&gt;
&lt;th&gt;Throughput Real&lt;/th&gt;
&lt;th&gt;P95 Latency&lt;/th&gt;
&lt;th&gt;Success Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go gRPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;85 RPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;71.88 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NestJS gRPC&lt;/td&gt;
&lt;td&gt;78 RPS&lt;/td&gt;
&lt;td&gt;98.44 ms&lt;/td&gt;
&lt;td&gt;~85%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;¿Qué pasó aquí?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Serialización:&lt;/strong&gt; Node.js (V8) tiene un costo mayor al serializar/deserializar grandes volúmenes de JSON comparado con los Structs de Go y Protobuf.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Connection Pool:&lt;/strong&gt; Bajo presión extrema, el pool de conexiones de Prisma comenzó a saturarse (errores &lt;code&gt;P2024&lt;/code&gt;), provocando que &lt;strong&gt;NestJS perdiera el ~15% de los requests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Estabilidad:&lt;/strong&gt; Go mantuvo el 100% de éxito y latencias más predecibles, gracias a su manejo de goroutines y un GC más eficiente para este tipo de carga.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚖️ Conclusión: ¿Cuándo usar cuál?
&lt;/h2&gt;

&lt;p&gt;Basado en los datos, aquí está mi recomendación pragmática:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Quédate con NestJS si:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Estás construyendo un MVP o validando producto.&lt;/li&gt;
&lt;li&gt;  Tu equipo ya conoce TypeScript y valoras la velocidad de desarrollo.&lt;/li&gt;
&lt;li&gt;  La carga es moderada (&amp;lt; 300 RPS) y operaciones CRUD estándar (Small Data).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;BFF (Backend for Frontend):&lt;/strong&gt; Si solo necesitas orquestar llamadas a pocos servicios y la carga de serialización es baja.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🚀 Migra a Go si:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;BFF Complejo:&lt;/strong&gt; Si tu BFF necesita llamar a muchos microservicios, agregar lógica pesada, serializar grandes volúmenes de datos y hacer fan-out masivo, Go manejará la concurrencia mucho mejor.&lt;/li&gt;
&lt;li&gt;  Tu sistema realiza &lt;strong&gt;Bulk Operations / ETL&lt;/strong&gt; masivos constantemente (Large Data).&lt;/li&gt;
&lt;li&gt;  Necesitas manejar miles de conexiones concurrentes (ej. Gateways, Websockets masivos).&lt;/li&gt;
&lt;li&gt;  Tienes SLAs de latencia muy estrictos donde los picos del Garbage Collector de Node son inaceptables.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📖 Lee el análisis completo
&lt;/h2&gt;

&lt;p&gt;Este post es un resumen. El análisis detallado (con todas las tablas, gráficos, configuración de hardware y análisis de errores) es &lt;strong&gt;público y gratuito&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://buymeacoffee.com/alpha018/nestjs-vs-go-lo-que-los-datos-dicen-sobre-cundo-usar-cada-uno" rel="noopener noreferrer"&gt;Leer el artículo completo en Buy Me a Coffee&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;&lt;a href="https://github.com/Alpha018/grpc-http-performance-lab" rel="noopener noreferrer"&gt;Ver el código en GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💌 &lt;strong&gt;Agradecimientos Especiales&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A una chica que, sin saberlo, me empujó a seguir creando y programando en mi tiempo libre. A quien alguna vez fue mi chispa: para “YLP”, con gratitud… y con cicatrices que también enseñan.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Si te sirve este tipo de análisis, ¡cualquier feedback es bienvenido!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>backend</category>
      <category>nestjs</category>
      <category>performance</category>
    </item>
    <item>
      <title>🐳 Minecraft + Docker: My personal config to stop suffering with Java</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Thu, 05 Feb 2026 04:19:41 +0000</pubDate>
      <link>https://forem.com/alpha018/minecraft-docker-my-personal-config-to-stop-suffering-with-java-35a7</link>
      <guid>https://forem.com/alpha018/minecraft-docker-my-personal-config-to-stop-suffering-with-java-35a7</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/alpha018/minecraft-docker-mi-configuracion-personal-para-no-sufrir-con-java-27k"&gt;🇪🇸 Lee este post en Español&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm no Java guru, and I'll be honest: managing Minecraft servers has always felt like a weird puzzle to me. Even though Minecraft might look like a "random" game about placing blocks, the technical management behind a server (threads, memory, garbage collection) is a fascinating optimization challenge.&lt;/p&gt;

&lt;p&gt;Back in the day, I tried creating plugins (with... "interesting" results), but I learned the hard way that the real battle is almost always the configuration.&lt;/p&gt;

&lt;p&gt;Has this happened to you? You want to play Survival with friends, you search for "best paper 1.21 config", and you end up with 20 open tabs and three wikis that contradict each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Initiative: Enough Chaos
&lt;/h2&gt;

&lt;p&gt;Tired of copying and pasting the same configuration lines over and over again, I decided to build &lt;strong&gt;&lt;a href="https://github.com/Alpha018/paper-config-optimized" rel="noopener noreferrer"&gt;Paper Config Optimized&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I didn't want to make "just another guide". I wanted a place to truly centralize the community's best practices into ready-to-use files. In fact, I've become such a fan of this "infrastructure as code" approach that I recently made my first contribution to the official Docker image repository we use (PR #3076 in &lt;code&gt;itzg/docker-minecraft-server&lt;/code&gt;) and plan to keep contributing to improve the ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  "The Recipe" (Configuration)
&lt;/h2&gt;

&lt;p&gt;Here is the configuration I always use. It's basically my "copy, paste, and forget" template.&lt;/p&gt;

&lt;p&gt;The important thing here is that we are telling Docker two key things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;"Use Aikar's Flags"&lt;/strong&gt;: So Java doesn't get picky with memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Download configs from the repo"&lt;/strong&gt;: So the game runs smoothly without having to touch anything.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;itzg/minecraft-server&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paper-lite&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;25565:25565"&lt;/span&gt;

    &lt;span class="c1"&gt;# Interactive console (never hurts to see what's happening)&lt;/span&gt;
    &lt;span class="na"&gt;stdin_open&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Mojang bureaucracy and software choice (Paper flies)&lt;/span&gt;
      &lt;span class="na"&gt;EULA&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TRUE"&lt;/span&gt;
      &lt;span class="na"&gt;TYPE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAPER"&lt;/span&gt;

      &lt;span class="c1"&gt;# Always the latest. Living on the edge.&lt;/span&gt;
      &lt;span class="na"&gt;VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LATEST"&lt;/span&gt;

      &lt;span class="c1"&gt;# We activate Aikar's flags.&lt;/span&gt;
      &lt;span class="c1"&gt;# Trust me, you don't want to manage the Garbage Collector manually.&lt;/span&gt;
      &lt;span class="na"&gt;USE_AIKAR_FLAGS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;

      &lt;span class="c1"&gt;# Timezone (change to yours so logs make sense)&lt;/span&gt;
      &lt;span class="na"&gt;TZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;America/Santiago"&lt;/span&gt;

      &lt;span class="c1"&gt;# ✨ THE MAGIC:&lt;/span&gt;
      &lt;span class="c1"&gt;# Automatically injects optimized configs from the repo at startup.&lt;/span&gt;
      &lt;span class="na"&gt;PAPER_CONFIG_REPO&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://raw.githubusercontent.com/Alpha018/paper-config-optimized/main"&lt;/span&gt;

    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./minecraft-data:/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to run this?
&lt;/h3&gt;

&lt;p&gt;It's as simple as putting that into a &lt;code&gt;docker-compose.yml&lt;/code&gt; file, opening a terminal in the folder, and throwing in a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚖️ Balance: Pros and Cons
&lt;/h2&gt;

&lt;p&gt;As with everything in engineering, there are no silver bullets. This configuration is my favorite, but we have to be transparent:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ The Good (Pros)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: Go from "zero" to "optimized server" in 2 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance&lt;/strong&gt;: By using &lt;code&gt;PAPER_CONFIG_REPO&lt;/code&gt;, if performance improvements come out tomorrow, you just have to restart the container to apply them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability&lt;/strong&gt;: Using &lt;em&gt;Aikar's Flags&lt;/em&gt; eliminates 90% of lag spikes caused by Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ The Bad (Cons)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Black Box&lt;/strong&gt;: If you like manually adjusting every millimeter of &lt;code&gt;view-distance&lt;/code&gt;, you might feel like you're losing some control (although you can always overwrite the files).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency&lt;/strong&gt;: You depend on my repository (or your own fork) being online to download the configs at startup.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 For Advanced Users
&lt;/h2&gt;

&lt;p&gt;This configuration is ideal for what I call "Lite Technical Survival". But if you are planning to set up a massive public community (50+ players) or want to understand why 12GB of RAM is my magic number for large servers, I wrote a much deeper technical guide.&lt;/p&gt;

&lt;p&gt;☕ &lt;strong&gt;&lt;a href="https://buymeacoffee.com/alpha018/ultra-optimized-papermc-docker-a-technical-deep-dive" rel="noopener noreferrer"&gt;Check out the Advanced Technical Guide on Buy Me a Coffee&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💌 Special Acknowledgments
&lt;/h3&gt;

&lt;p&gt;To a girl who, without knowing it, pushed me to keep creating and coding in my free time. To the one who was once my spark: for "YLP", with gratitude... and with scars that also teach.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>minecraft</category>
      <category>performance</category>
      <category>java</category>
    </item>
    <item>
      <title>🐳 Minecraft + Docker: Mi configuración personal para no sufrir con Java</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Thu, 05 Feb 2026 04:18:11 +0000</pubDate>
      <link>https://forem.com/alpha018/minecraft-docker-mi-configuracion-personal-para-no-sufrir-con-java-27k</link>
      <guid>https://forem.com/alpha018/minecraft-docker-mi-configuracion-personal-para-no-sufrir-con-java-27k</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/alpha018/minecraft-docker-my-personal-config-to-stop-suffering-with-java-35a7"&gt;🇺🇸 Read this post in English&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No soy ningún gurú de Java, y seré honesto: gestionar servidores de Minecraft siempre me pareció un rompecabezas extraño. A pesar de que Minecraft pueda parecer un juego "random" de poner cubitos, la gestión técnica detrás de un servidor (hilos, memoria, recolección de basura) es un reto de optimización fascinante.&lt;/p&gt;

&lt;p&gt;En su momento intenté crear plugins (con resultados... "interesantes"), pero aprendí a la mala que la verdadera batalla casi siempre es la configuración.&lt;/p&gt;

&lt;p&gt;¿Te ha pasado? Quieres jugar un Survival con amigos, buscas "mejor configuración paper 1.21" y terminas con 20 pestañas abiertas y tres wikis que se contradicen.&lt;/p&gt;

&lt;h2&gt;
  
  
  La Iniciativa: Basta de Caos
&lt;/h2&gt;

&lt;p&gt;Cansado de copiar y pegar las mismas líneas de configuración una y otra vez, se me ocurrió armar &lt;strong&gt;&lt;a href="https://github.com/Alpha018/paper-config-optimized" rel="noopener noreferrer"&gt;Paper Config Optimized&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No quería hacer "otra guía más". Quería un lugar donde centralizar de verdad las mejores prácticas de la comunidad en archivos listos para usar. De hecho, me he vuelto tan fan de esta "infraestructura como código" que hace poco hice mi primera contribución al repositorio oficial de la imagen de Docker que usamos (PR #3076 en &lt;code&gt;itzg/docker-minecraft-server&lt;/code&gt;) y planeo seguir aportando para mejorar el ecosistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  "La Receta" (Configuración)
&lt;/h2&gt;

&lt;p&gt;Te dejo por aquí la configuración que uso siempre. Es básicamente mi plantilla de "copiar, pegar y olvidarse".&lt;/p&gt;

&lt;p&gt;Lo importante aquí es que le estamos diciendo a Docker dos cosas clave:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;"Usa Aikar's Flags"&lt;/strong&gt;: Para que Java no se ponga caprichoso con la memoria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Descargar las configs del repositorio"&lt;/strong&gt;: Para que el juego corra fluido sin tener que tocar nada.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;itzg/minecraft-server&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;paper-lite&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;25565:25565"&lt;/span&gt;

    &lt;span class="c1"&gt;# Consola interactiva (nunca está de más para ver qué pasa)&lt;/span&gt;
    &lt;span class="na"&gt;stdin_open&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Papeleo burocrático de Mojang y elección del software (Paper vuela)&lt;/span&gt;
      &lt;span class="na"&gt;EULA&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TRUE"&lt;/span&gt;
      &lt;span class="na"&gt;TYPE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAPER"&lt;/span&gt;

      &lt;span class="c1"&gt;# Siempre a la última. Vivir al límite.&lt;/span&gt;
      &lt;span class="na"&gt;VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LATEST"&lt;/span&gt;

      &lt;span class="c1"&gt;# Activamos las flags de Aikar.&lt;/span&gt;
      &lt;span class="c1"&gt;# Créeme, no quieres gestionar el Garbage Collector manualmente.&lt;/span&gt;
      &lt;span class="na"&gt;USE_AIKAR_FLAGS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;

      &lt;span class="c1"&gt;# Zona horaria (cámbiala a la tuya para no volverte loco con los logs)&lt;/span&gt;
      &lt;span class="na"&gt;TZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;America/Santiago"&lt;/span&gt;

      &lt;span class="c1"&gt;# ✨ LA MAGIA:&lt;/span&gt;
      &lt;span class="c1"&gt;# Inyecta las configs optimizadas del repositorio automáticamente al iniciar.&lt;/span&gt;
      &lt;span class="na"&gt;PAPER_CONFIG_REPO&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://raw.githubusercontent.com/Alpha018/paper-config-optimized/main"&lt;/span&gt;

    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./minecraft-data:/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Cómo correr esto?
&lt;/h3&gt;

&lt;p&gt;Es tan simple como meter eso en un archivo &lt;code&gt;docker-compose.yml&lt;/code&gt;, abrir una terminal en la carpeta y tirar un:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚖️ Balance: Pros y Contras
&lt;/h2&gt;

&lt;p&gt;Como en todo en ingeniería, no hay balas de plata. Esta configuración es mi favorita, pero hay que ser transparentes:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Lo Bueno (Pros)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Velocidad&lt;/strong&gt;: Pasas de "cero" a "servidor optimizado" en 2 minutos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mantenimiento&lt;/strong&gt;: Al usar &lt;code&gt;PAPER_CONFIG_REPO&lt;/code&gt;, si mañana salen nuevas mejoras de rendimiento, solo tienes que reiniciar el contenedor para aplicarlas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estabilidad&lt;/strong&gt;: Usar las &lt;em&gt;Aikar's Flags&lt;/em&gt; elimina el 90% de los tirones de lag por culpa de Java.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Lo Malo (Contras)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caja Negra&lt;/strong&gt;: Si te gusta ajustar cada milímetro de la &lt;code&gt;view-distance&lt;/code&gt; a mano, sentirás que pierdes algo de control (aunque siempre puedes sobrescribir los archivos).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencia&lt;/strong&gt;: Dependes de que mi repositorio (o el fork que te hagas) esté en línea para descargar las configs al inicio.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Para Usuarios Avanzados
&lt;/h2&gt;

&lt;p&gt;Esta configuración es ideal para lo que llamo "Survival Técnico Lite". Pero si estás planeando montar una comunidad pública masiva (50+ jugadores) o quieres entender por qué 12GB de RAM es mi número mágico para servidores grandes, escribí una guía técnica mucho más profunda.&lt;/p&gt;

&lt;p&gt;☕ &lt;strong&gt;&lt;a href="https://buymeacoffee.com/alpha018/papermc-ultra-optimizado-con-docker-una-inmersin-tcnica" rel="noopener noreferrer"&gt;Échale un ojo a la Guía Técnica Avanzada en Buy Me a Coffee&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  💌 Agradecimientos Especiales
&lt;/h3&gt;

&lt;p&gt;A una chica que, sin saberlo, me empujó a seguir creando y programando en mi tiempo libre. A quien alguna vez fue mi chispa: para “YLP”, con gratitud… y con cicatrices que también enseñan.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>minecraft</category>
      <category>performance</category>
      <category>java</category>
    </item>
    <item>
      <title>🚀 Supercarga la Autenticación en NestJS con Firebase</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Sun, 04 Jan 2026 09:13:33 +0000</pubDate>
      <link>https://forem.com/alpha018/supercarga-la-autenticacion-en-nestjs-con-firebase-1kc0</link>
      <guid>https://forem.com/alpha018/supercarga-la-autenticacion-en-nestjs-con-firebase-1kc0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/alpha018/integrating-firebase-authentication-into-nestjs-with-nestjs-firebase-auth-55m6"&gt;Read this post in English&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si vienes del mundo de &lt;strong&gt;NestJS&lt;/strong&gt;, te encantan los decoradores, la inyección de dependencias y el tipado fuerte. Pero cuando se trata de integrar &lt;strong&gt;Firebase Authentication&lt;/strong&gt;, a menudo se siente como una tarea pesada: &lt;em&gt;guards repetitivos&lt;/em&gt;, verificación manual de tokens y manejo de roles &lt;em&gt;desordenado&lt;/em&gt; que ensucia nuestros controladores.&lt;/p&gt;

&lt;p&gt;Hoy quiero reintroducir &lt;strong&gt;&lt;code&gt;nestjs-firebase-auth&lt;/code&gt;&lt;/strong&gt;, una librería diseñada para cerrar esa brecha y tratar la autenticación de Firebase con el respeto que merece en una arquitectura moderna de NestJS.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 ¿Por qué creé esto?
&lt;/h2&gt;

&lt;p&gt;Firebase Authentication es robusto, pero el SDK Admin oficial es solo eso: un SDK. No sabe nada sobre Guards, Decoradores o Inyección de Dependencias de NestJS.&lt;/p&gt;

&lt;p&gt;No deberías tener que escribir middleware personalizado para decodificar tokens o verificar claims manualmente en cada controlador. &lt;code&gt;nestjs-firebase-auth&lt;/code&gt; cierra esta brecha, dándote una API simplificada y declarativa para asegurar tu aplicación.&lt;/p&gt;

&lt;p&gt;Con el último lanzamiento &lt;strong&gt;v1.9.0&lt;/strong&gt;, he pulido la experiencia aún más con decoradores más limpios y una mejor integración con otros servicios de Firebase como Firestore.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalación
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @alpha018/nestjs-firebase-auth firebase-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Profundizando en el Código
&lt;/h2&gt;

&lt;p&gt;Veamos ejemplos más realistas de lo que puedes lograr.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Autenticación Declarativa &lt;code&gt;(@Auth)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Olvídate de importar y vincular manualmente los guards con &lt;code&gt;@UseGuards(FirebaseGuard)&lt;/code&gt;. Ahora tienes un decorador &lt;code&gt;@Auth()&lt;/code&gt; limpio que hace clara tu intención.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 🛡️ Protege todo este controlador&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getProfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Estos datos son seguros.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Control de Acceso Basado en Roles (RBAC)
&lt;/h3&gt;

&lt;p&gt;Manejar roles no debería ser complicado. Utilizo los Custom Claims de Firebase para almacenar los roles del usuario, y el decorador &lt;code&gt;@Roles&lt;/code&gt; para hacerlos cumplir sin escribir una sola línea de lógica de validación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Roles&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdminController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADMIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPERUSER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ⛔ Solo permite usuarios con estos roles&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getDashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Datos de administración ultra secretos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; El decorador &lt;code&gt;@Roles&lt;/code&gt; activa automáticamente la lógica de validación de roles subyacente cuando se usa con &lt;code&gt;@Auth&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Integrando con otros servicios de Firebase
&lt;/h3&gt;

&lt;p&gt;¿Necesitas hablar con Firestore o enviar un mensaje FCM específico? Siempre ha sido posible, pero quiero destacar lo fácil que es acceder a la instancia inicializada de &lt;code&gt;admin.app.App&lt;/code&gt; directamente desde mi provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FirebaseProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getFirestore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin/firestore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;firebaseProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;saveUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 🔥 Usa la instancia de app del módulo de auth para Firestore&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirestore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firebaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Mejores Casos de Uso
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Aplicaciones SaaS&lt;/strong&gt;: Donde necesitas autenticación robusta y segura con configuración mínima.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservicios&lt;/strong&gt;: Compartir lógica de autenticación a través de múltiples servicios NestJS fácilmente usando un enfoque de librería compartida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sistemas RBAC&lt;/strong&gt;: Apps que requieren control granular sobre quién puede hacer qué (Admins vs. Usuarios).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚠️ Trade-offs (Honestidad Ante Todo)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validación Remota&lt;/strong&gt;: Por defecto, verifico los roles obteniendo el registro de usuario desde Firebase. Esto asegura que los roles estén &lt;em&gt;siempre&lt;/em&gt; actualizados (sin tokens obsoletos), pero incurre en una pequeña latencia de red.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validación Local&lt;/strong&gt;: Puedes optar por &lt;code&gt;useLocalRoles: true&lt;/code&gt; para validar contra los claims del token ID directamente (cero latencia), pero debes aceptar que los cambios de roles efectivamente se actualizan solo cuando el usuario refresca su token.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💌 Agradecimientos Especiales
&lt;/h2&gt;

&lt;p&gt;Este proyecto ha sido construido con muchas horas de dedicación y amor por el código.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Para una chica que siempre me inspira en silencio, y su sola existencia me incentiva a seguir programando en mis tiempos libres, gracias "YLP".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ☕ Apoya el Proyecto
&lt;/h2&gt;

&lt;p&gt;Si encontraste este proyecto útil o interesante, por favor considera apoyarlo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⭐️ &lt;strong&gt;Estrella en GitHub&lt;/strong&gt;: Es gratis y ayuda a otros a encontrar la librería.&lt;/li&gt;
&lt;li&gt;☕ &lt;strong&gt;Cómprame un Café&lt;/strong&gt;: Si quieres ir un paso más allá, puedes hacerlo en &lt;a href="https://buymeacoffee.com/alpha018" rel="noopener noreferrer"&gt;buymeacoffee.com/alpha018&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Pruébalo y Contribuye
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt;: &lt;a href="https://github.com/Alpha018/nestjs-firebase-auth" rel="noopener noreferrer"&gt;github.com/Alpha018/nestjs-firebase-auth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autor&lt;/strong&gt;: &lt;a href="https://dev.to/alpha018"&gt;dev.to/alpha018&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Qué piensas? ¿Estás listo para simplificar tu flujo de autenticación? 👇&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>typescript</category>
      <category>nestjs</category>
      <category>security</category>
    </item>
    <item>
      <title>🚀 NestJS + RedisOM: Elevando el manejo de Estado a otro nivel</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Sat, 03 Jan 2026 21:19:40 +0000</pubDate>
      <link>https://forem.com/alpha018/nestjs-redisom-elevando-el-manejo-de-estado-a-otro-nivel-46bo</link>
      <guid>https://forem.com/alpha018/nestjs-redisom-elevando-el-manejo-de-estado-a-otro-nivel-46bo</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🇺🇸 &lt;a href="https://dev.to/alpha018/nestjs-redisom-taking-state-management-to-the-next-level-5gli"&gt;Read this post in English&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si vienes del mundo de &lt;strong&gt;NestJS&lt;/strong&gt;, amas los decoradores, la inyección de dependencias y el tipado fuerte. Pero cuando toca integrar &lt;strong&gt;Redis&lt;/strong&gt;, a menudo sentimos que retrocedemos 10 años: &lt;em&gt;magic strings&lt;/em&gt;, parsers manuales de JSON y comandos &lt;em&gt;low-level&lt;/em&gt; que ensucian nuestra lógica de negocio.&lt;/p&gt;

&lt;p&gt;Hoy quiero presentarles &lt;strong&gt;&lt;code&gt;nestjs-redisom&lt;/code&gt;&lt;/strong&gt;, una librería open-source diseñada para cerrar esa brecha y tratar a Redis con el respeto que se merece en una arquitectura empresarial moderna.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 ¿Por qué creé esto?
&lt;/h2&gt;

&lt;p&gt;Redis ha evolucionado. Ya no es solo un caché key-value. Con &lt;strong&gt;Redis Stack&lt;/strong&gt; (RedisJSON + RediSearch), se ha convertido en una base de datos de documentos en tiempo real increíblemente potente.&lt;/p&gt;

&lt;p&gt;Sin embargo, usar estas features desde Node.js suele ser verboso. &lt;strong&gt;Redis OM&lt;/strong&gt; (la librería oficial) ayuda, pero integrarla en NestJS requería mucho &lt;em&gt;boilerplate&lt;/em&gt;. &lt;code&gt;nestjs-redisom&lt;/code&gt; elimina esa fricción, dándote una experiencia nativa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalación
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;nestjs-redisom redis-om redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Profundizando en el Código
&lt;/h2&gt;

&lt;p&gt;Veamos ejemplos más realistas de lo que puedes lograr.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Modelado de Datos Complejos (Anidados)
&lt;/h3&gt;

&lt;p&gt;No estamos limitados a strings planos. Podemos modelar objetos complejos con validación implícita.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Definimos una clase anidada&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;indexed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Indexado para buscar "Usuarios en Madrid"&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;zipCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Definimos la Entidad Principal&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;textSearch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// Mapeo anidado&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Arrays de strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Búsquedas Avanzadas (Fluent API)
&lt;/h3&gt;

&lt;p&gt;Aquí es donde &lt;code&gt;nestjs-redisom&lt;/code&gt; brilla. Olvídate de aprender la sintaxis de comandos de RediSearch (&lt;code&gt;FT.SEARCH index "@field:value ..."&lt;/code&gt;). Usa esta API fluida y tipada.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Encuentra usuarios que vivan en 'New York', tengan el rol 'admin' y cuya bio mencione 'typescript'"&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address_city&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Busca en objeto anidado&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;roles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;// Busca en Array&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;// Full-Text Search&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                      &lt;span class="c1"&gt;// Paginación nativa&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Expiración de Documentos (TTL)
&lt;/h3&gt;

&lt;p&gt;Manejar sesiones o caché temporal es trivial. No necesitas scripts de Lua ni nada por el estilo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Crea una sesión y haz que expire en 1 hora&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idField&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Mejores Casos de Uso
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High-Speed Objects&lt;/strong&gt;: Carritos de compra, Perfiles de Jugador, Sesiones. Datos que lees/escribes 1000 veces por segundo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caché con "Poderes"&lt;/strong&gt;: A veces necesitas invalidar caché por criterio (&lt;em&gt;"borrar caché de todos los productos de la categoría X"&lt;/em&gt;). Con Redis normal es imposible (o lento con &lt;code&gt;KEYS *&lt;/code&gt;). Con RedisOM es una &lt;em&gt;query&lt;/em&gt; de O(1) o O(N log N).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geo-Spatial Features&lt;/strong&gt;: "Encuentra conductores cerca de mi", usando la potencia nativa de Redis para geo-hashing.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚠️ Trade-offs (Honestidad ante todo)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RAM es Dinero&lt;/strong&gt;: Redis guarda todo en memoria. No uses esto para guardar logs de auditoría de 5 años.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eventual Consistency&lt;/strong&gt;: Los índices de búsqueda se actualizan asíncronamente (milisegundos). No es ACID estricto para búsquedas inmediatas post-escritura.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💌 Agradecimientos Especiales
&lt;/h2&gt;

&lt;p&gt;Este proyecto ha sido construido con muchas horas de dedicación y amor por el código.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Para una chica que siempre me inspira en silencio, y su sola existencia me incentiva a seguir programando en mis tiempos libres, gracias "YLP".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ☕ Apoya el Proyecto
&lt;/h2&gt;

&lt;p&gt;Si este proyecto te ha sido útil o te parece interesante, considera apoyarlo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⭐️ &lt;strong&gt;Star en GitHub&lt;/strong&gt;: Es gratis y ayuda a que más gente lo encuentre.&lt;/li&gt;
&lt;li&gt;☕ &lt;strong&gt;Invítame un Café&lt;/strong&gt;: Si quieres ir un paso más allá, puedes hacerlo en &lt;a href="https://buymeacoffee.com/alpha018" rel="noopener noreferrer"&gt;buymeacoffee.com/alpha018&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Pruébalo y Contribuye
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt;: &lt;a href="https://github.com/Alpha018/nestjs-redisom" rel="noopener noreferrer"&gt;github.com/Alpha018/nestjs-redisom&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autor&lt;/strong&gt;: &lt;a href="https://dev.to/alpha018"&gt;dev.to/alpha018&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Qué opinan? ¿Le darán una oportunidad a Redis como base de datos de documentos? 👇&lt;/p&gt;

</description>
      <category>redis</category>
      <category>typescript</category>
      <category>node</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>🚀 NestJS + RedisOM: Taking State Management to the Next Level</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Fri, 02 Jan 2026 01:39:59 +0000</pubDate>
      <link>https://forem.com/alpha018/nestjs-redisom-taking-state-management-to-the-next-level-5gli</link>
      <guid>https://forem.com/alpha018/nestjs-redisom-taking-state-management-to-the-next-level-5gli</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🇪🇸 &lt;a href="https://dev.to/alpha018/nestjs-redisom-elevando-el-manejo-de-estado-a-otro-nivel-46bo"&gt;Lee este post en Español&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you come from the &lt;strong&gt;NestJS&lt;/strong&gt; world, you love decorators, dependency injection, and strong typing. But when it comes to integrating &lt;strong&gt;Redis&lt;/strong&gt;, it often feels like we're stepping back 10 years: &lt;em&gt;magic strings&lt;/em&gt;, manual JSON parsers, and &lt;em&gt;low-level&lt;/em&gt; commands that clutter our business logic.&lt;/p&gt;

&lt;p&gt;Today I want to introduce &lt;strong&gt;&lt;code&gt;nestjs-redisom&lt;/code&gt;&lt;/strong&gt;, an open-source library designed to bridge that gap and treat Redis with the respect it deserves in a modern enterprise architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why did I create this?
&lt;/h2&gt;

&lt;p&gt;Redis has evolved. It is no longer just a key-value cache. With &lt;strong&gt;Redis Stack&lt;/strong&gt; (RedisJSON + RediSearch), it has become an incredibly powerful real-time document database.&lt;/p&gt;

&lt;p&gt;However, using these features from Node.js is often verbose. &lt;strong&gt;Redis OM&lt;/strong&gt; (the official library) helps, but integrating it into NestJS required a lot of &lt;em&gt;boilerplate&lt;/em&gt;. &lt;code&gt;nestjs-redisom&lt;/code&gt; removes that friction, giving you a native experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;nestjs-redisom redis-om redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Deep Dive into the Code
&lt;/h2&gt;

&lt;p&gt;Let's look at more realistic examples of what you can achieve.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Complex Data Modeling (Nested)
&lt;/h3&gt;

&lt;p&gt;We aren't limited to flat strings. We can model complex objects with implicit validation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Define a Nested Class&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;indexed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Indexed to search "Users in Madrid"&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;zipCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Define the Main Entity&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;textSearch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// Nested mapping&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Advanced Searching (Fluent API)
&lt;/h3&gt;

&lt;p&gt;This is where &lt;code&gt;nestjs-redisom&lt;/code&gt; shines. Forget about learning RediSearch command syntax (&lt;code&gt;FT.SEARCH index "@field:value ..."&lt;/code&gt;). Use this fluent, typed API.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Find users living in 'New York', having the role 'admin', and whose bio mentions 'typescript'"&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address_city&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Search in nested object&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;roles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;// Search in Array&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;// Full-Text Search&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                      &lt;span class="c1"&gt;// Native pagination&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Document Expiration (TTL)
&lt;/h3&gt;

&lt;p&gt;Handling sessions or temporary cache is trivial. You don't need Lua scripts or anything like that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a session and make it expire in 1 hour&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idField&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Best Use Cases
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High-Speed Objects&lt;/strong&gt;: Shopping Carts, Player Profiles, Sessions. Data you read/write 1000 times per second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Powered-Up Cache&lt;/strong&gt;: Sometimes you need to invalidate cache by criteria (&lt;em&gt;"clear cache for all products in category X"&lt;/em&gt;). With standard Redis, this is impossible (or slow with &lt;code&gt;KEYS *&lt;/code&gt;). With RedisOM, it's an O(1) or O(N log N) &lt;em&gt;query&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geo-Spatial Features&lt;/strong&gt;: "Find drivers near me", using Redis native power for geo-hashing.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚠️ Trade-offs (Honesty First)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RAM is Money&lt;/strong&gt;: Redis stores everything in memory. Don't use this to store 5 years of audit logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eventual Consistency&lt;/strong&gt;: Search indexes update asynchronously (milliseconds). It is not strict ACID for immediate post-write searches.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💌 Special Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This project has been built with many hours of dedication and love for code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To a girl who always inspires me in silence, and whose mere existence incentivizes me to keep programming in my free time, thank you "YLP".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ☕ Support the Project
&lt;/h2&gt;

&lt;p&gt;If you found this project useful or interesting, please consider supporting it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⭐️ &lt;strong&gt;Star on GitHub&lt;/strong&gt;: It's free and helps others find the library.&lt;/li&gt;
&lt;li&gt;☕ &lt;strong&gt;Buy me a Coffee&lt;/strong&gt;: If you want to go the extra mile, you can do so at &lt;a href="https://buymeacoffee.com/alpha018" rel="noopener noreferrer"&gt;buymeacoffee.com/alpha018&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Try it and Contribute
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt;: &lt;a href="https://github.com/Alpha018/nestjs-redisom" rel="noopener noreferrer"&gt;github.com/Alpha018/nestjs-redisom&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Author&lt;/strong&gt;: &lt;a href="https://dev.to/alpha018"&gt;dev.to/alpha018&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do you think? Will you give Redis a chance as a document database? 👇&lt;/p&gt;

</description>
      <category>redis</category>
      <category>typescript</category>
      <category>node</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>🚀 Supercharge NestJS Authentication with Firebase</title>
      <dc:creator>Tomás Alegre Sepúlveda</dc:creator>
      <pubDate>Tue, 10 Sep 2024 22:56:14 +0000</pubDate>
      <link>https://forem.com/alpha018/integrating-firebase-authentication-into-nestjs-with-nestjs-firebase-auth-55m6</link>
      <guid>https://forem.com/alpha018/integrating-firebase-authentication-into-nestjs-with-nestjs-firebase-auth-55m6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🇪🇸 &lt;a href="https://dev.to/alpha018/supercarga-la-autenticacion-en-nestjs-con-firebase-1kc0"&gt;Lee este post en Español&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're building a modern application with NestJS, you probably love its modularity, decorators, and type safety. But when it comes to authentication, integrating external providers often feels like a chore—boilerplate guards, manual token verification, and messy role handling.&lt;/p&gt;

&lt;p&gt;Today, I want to re-introduce &lt;code&gt;nestjs-firebase-auth&lt;/code&gt;, a library designed to make Firebase Authentication feel native to the NestJS ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Why this library?
&lt;/h2&gt;

&lt;p&gt;Firebase Authentication is robust, but the official Admin SDK is just that—an SDK. It doesn't know about NestJS Guards, Decorators, or Dependency Injection.&lt;/p&gt;

&lt;p&gt;You shouldn't have to write custom middleware to decode tokens or manually check claims in every controller. &lt;code&gt;nestjs-firebase-auth&lt;/code&gt; bridges this gap, giving you a simplified, declarative API for securing your application.&lt;/p&gt;

&lt;p&gt;With the latest &lt;strong&gt;v1.9.0&lt;/strong&gt; release, I've polished the experience even further with cleaner decorators and better integration with other Firebase services like Firestore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @alpha018/nestjs-firebase-auth firebase-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛠️ Deep Dive into the Code
&lt;/h2&gt;

&lt;p&gt;Let's look at how this changes your daily workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Declarative Authentication (&lt;code&gt;@Auth&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Forget about manually importing and binding guards with &lt;code&gt;@UseGuards(FirebaseGuard)&lt;/code&gt;. You now have a clean &lt;code&gt;@Auth()&lt;/code&gt; decorator that makes your intention clear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 🛡️ Protects this entire controller&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getProfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This data is secure.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Role-Based Access Control (RBAC)
&lt;/h3&gt;

&lt;p&gt;Managing roles shouldn't be complicated. I use Firebase Custom Claims to store user roles, and the &lt;code&gt;@Roles&lt;/code&gt; decorator to enforce them without writing a single line of validation logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Roles&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdminController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADMIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPERUSER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ⛔ Only allows users with these roles&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getDashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Top secret admin data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;@Roles&lt;/code&gt; decorator automatically triggers the underlying role validation logic when used with &lt;code&gt;@Auth&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Type-Safe User Access
&lt;/h3&gt;

&lt;p&gt;Accessing the current user's data is straightforward and type-safe using &lt;code&gt;@FirebaseUser&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;me&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;getProfile&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;FirebaseUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DecodedIdToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// `user` is the standard Firebase DecodedIdToken&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Integrating with other Firebase Services
&lt;/h3&gt;

&lt;p&gt;Need to talk to Firestore or send a clear-cut FCM message? It has always been possible, but I want to highlight how easy it is to access the initialized &lt;code&gt;admin.app.App&lt;/code&gt; instance directly from my provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FirebaseProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@alpha018/nestjs-firebase-auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getFirestore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin/firestore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;firebaseProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;saveUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 🔥 Use the auth module's app instance for Firestore&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirestore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firebaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 Best Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SaaS Applications&lt;/strong&gt;: Where you need robust, secure authentication with minimal setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices&lt;/strong&gt;: Sharing authentication logic across multiple NestJS services easily using a shared library approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RBAC Systems&lt;/strong&gt;: Apps that require granular control over who can do what (Admins vs. Users).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚠️ Trade-offs (Honesty First)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remote Validation&lt;/strong&gt;: By default, I verify roles by fetching the user record from Firebase. This ensures roles are &lt;em&gt;always&lt;/em&gt; up to date (no stale tokens), but it incurs a small network latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Validation&lt;/strong&gt;: You can opt-in to &lt;code&gt;useLocalRoles: true&lt;/code&gt; to validate against the ID token's claims directly (zero latency), but you must accept that role changes effectively update only when the user refreshes their token.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💌 Special Acknowledgments
&lt;/h2&gt;

&lt;p&gt;This project has been built with many hours of dedication and love for code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To a girl who always inspires me in silence, and whose mere existence incentivizes me to keep programming in my free time, thank you "YLP".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ☕ Support the Project
&lt;/h2&gt;

&lt;p&gt;If you found this project useful or interesting, please consider supporting it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⭐️ &lt;strong&gt;Star on GitHub&lt;/strong&gt;: It's free and helps others find the library.&lt;/li&gt;
&lt;li&gt;☕ &lt;strong&gt;Buy me a Coffee&lt;/strong&gt;: If you want to go the extra mile, you can do so at &lt;a href="https://buymeacoffee.com/alpha018" rel="noopener noreferrer"&gt;buymeacoffee.com/alpha018&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔗 Try it and Contribute
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo&lt;/strong&gt;: &lt;a href="https://github.com/Alpha018/nestjs-firebase-auth" rel="noopener noreferrer"&gt;github.com/Alpha018/nestjs-firebase-auth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Author&lt;/strong&gt;: &lt;a href="https://dev.to/alpha018"&gt;dev.to/alpha018&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do you think? Are you ready to simplify your authentication flow? 👇&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>typescript</category>
      <category>nestjs</category>
      <category>security</category>
    </item>
  </channel>
</rss>
