Angular Signals en producción: las prácticas que realmente marcan la diferencia
Cuando Angular introdujo Signals como parte de su modelo de reactividad moderno, muchos equipos los adoptaron rápido. Pero adoptarlos y usarlos bien son dos cosas muy distintas. Después de trabajar con este patrón en proyectos reales, queda claro que la mayoría de los problemas de rendimiento y bugs difíciles de rastrear vienen de unas pocas malas prácticas que se repiten una y otra vez.
Este artículo resume las reglas más importantes que aplica Leo Lanese —un desarrollador con experiencia real en producción con Angular Signals— y que cualquier equipo de frontend debería tener en cuenta hoy, en julio de 2026, cuando Signals ya es el estándar de facto para la reactividad en Angular.
No es teoría. Son decisiones concretas que cambian la calidad del código, la facilidad de mantenimiento y el rendimiento de las aplicaciones.
1. Los valores de un Signal son inmutables — sin excepciones
Este es el error número uno. Un Signal solo notifica a sus consumidores cuando se llama a .set() o .update(). Si en lugar de eso se muta el valor directamente —haciendo un .push() a un array o asignando una propiedad a un objeto— Angular no detecta ningún cambio porque la referencia es la misma.
La regla es clara: cada escritura a un Signal debe producir un valor completamente nuevo. Para arrays, eso significa usar operadores como el spread operator ([...arr, nuevoItem]) o .filter() en lugar de .push() o .splice(). Para objetos, se usa el spread de objeto ({ ...obj, propiedad: nuevoValor }) en lugar de asignaciones directas.
Esto no es una preferencia de estilo. Es lo que hace que el sistema de reactividad funcione correctamente. Sin esta regla, la UI puede quedar desincronizada con el estado real de la aplicación, generando bugs que son extremadamente difíciles de reproducir y rastrear.
2. computed() es para derivaciones puras — y effect() es para efectos secundarios reales
computed() está diseñado para ser una derivación pura y sincrónica. Angular puede re-evaluarlo más de una vez antes de que su valor sea leído, así que meter dentro una llamada HTTP, un acceso a localStorage o un log es una receta para el desastre: ese trabajo se ejecutará con una frecuencia que no se controla.
La separación correcta es esta: todo lo que sea una derivación matemática o lógica del estado va en computed(). Todo lo que tenga efectos secundarios reales —escribir en localStorage, llamar a una librería externa, analytics, manipulación manual del DOM— va en effect(). Y dentro de un effect(), si se necesita ejecutar código que no debe ser rastreado por el grafo de reactividad, se usa untracked().
Otro error frecuente es usar effect() para sincronizar un Signal con otro. Esto construye una ruta de sincronización imperativa y manual para algo que computed() ya maneja de forma declarativa y automática. La alternativa correcta cuando se necesita un valor derivado que también sea sobrescribible es linkedSignal().
3. Signals granulares y evitar el churn de referencias
Un error de arquitectura muy común es agrupar todo el estado de un componente en un solo Signal gigante. El problema: cualquier actualización a cualquier campo invalida todos los computed() y effect() que leen ese objeto, incluso los que solo dependen de un campo que no cambió.
La regla práctica es simple: solo se agrupan campos en un Signal si siempre se leen y escriben juntos. Si no, se separan. Signals granulares significan que cada consumidor solo se re-ejecuta cuando el dato que realmente le importa cambia.
Un problema relacionado y menos obvio es el churn de referencias en computed(). Si un computed devuelve un objeto o array nuevo en cada ejecución —aunque sea estructuralmente idéntico al anterior— cada consumidor lo trata como un cambio. Componentes con OnPush se re-renderizan, effects se re-disparan, y el rendimiento se degrada silenciosamente. La solución es proveer una función de igualdad personalizada o, mejor aún, separar el computed en primitivos independientes.
¿Cómo aplica esto en tu empresa?
Estas prácticas son especialmente relevantes para equipos que desarrollan aplicaciones de negocio en Angular: dashboards, módulos de gestión, integraciones con ERPs como Odoo, o aplicaciones internas para empresas en Perú y LATAM.
Un Signal mal usado en un componente de reportes puede hacer que toda la tabla se re-renderice con cada keystroke del usuario. Un computed() con una llamada HTTP adentro puede disparar peticiones al servidor de forma impredecible. Y un Signal monolítico que agrupa todo el estado de un módulo complejo puede convertir una aplicación rápida en una lenta sin que nadie entienda exactamente por qué.
Las acciones concretas para cualquier equipo de desarrollo son estas:
- Auditar los Signals existentes y verificar que ninguna escritura mute el valor directamente
- Revisar los templates en busca de llamadas a métodos ({{ getTotal() }}) y reemplazarlos con computed()
- Evaluar si los Signals grandes se pueden dividir en unidades más granulares
- Verificar que ningún computed() tenga efectos secundarios
- Agregar funciones de igualdad personalizadas a los computed() que retornan objetos o arrays
Estos cambios no requieren reescribir toda la aplicación. Se pueden aplicar incrementalmente, módulo por módulo, y el impacto en rendimiento y mantenibilidad es inmediato.
Conclusión
Angular Signals es una herramienta poderosa, pero su potencial solo se realiza cuando se trabaja con el grafo de reactividad, no alrededor de él. Las reglas son pocas y consistentes: inmutabilidad en las escrituras, pureza en los computed(), granularidad en el estado, y effect() solo para efectos secundarios reales.
En Consultoría-Ti trabajamos con equipos de desarrollo en Perú y LATAM que construyen aplicaciones Angular para sistemas de gestión empresarial, integraciones con Odoo y módulos internos. Si tu equipo está migrando a Signals o quiere mejorar la arquitectura de una aplicación existente, podemos ayudarte a hacerlo de forma ordenada y con criterio de producción.
¿Tienes preguntas sobre cómo aplicar estas prácticas en tu proyecto? Contáctanos aquí y conversamos.
Fuentes y Referencias
Leo Lanese — Angular Signals Best Practices I Apply in Production (Dev.to)
✨ Contenido generado con ContentFlow — Consultoría-Ti