localStorage en JavaScript: por qué deberías dejar de usar el almacenamiento local hoy
- 👤 Andrés Cruz
Si hoy estás construyendo una aplicación web moderna y sigues apoyándote en localStorage en JavaScript como solución de almacenamiento, probablemente estés acumulando problemas que todavía no ves… pero que llegarán.
localStorage apareció alrededor de 2009 y, aunque sigue siendo ampliamente documentado y enseñado, no ha evolucionado al ritmo de la web moderna. Y eso importa más de lo que muchos tutoriales admiten.
Antes vimos como usar los eventos de Luz Ambiental con JavaScript con AmbientLightSensor
Qué es localStorage en JavaScript (y por qué sigue apareciendo en todos los tutoriales)
localStorage es parte de la Web Storage API y permite guardar pares clave-valor en el navegador del usuario de forma persistente. A diferencia de sessionStorage, los datos no se eliminan al cerrar la pestaña o el navegador.
El problema no es qué es, sino por qué se sigue recomendando sin contexto.
Cómo funciona realmente el almacenamiento local en el navegador
- Los datos se guardan por origen (protocolo + dominio).
- Todo se almacena como cadenas UTF-16.
- Las operaciones son síncronas.
- No hay control de concurrencia, transacciones ni aislamiento.
Esto puede sonar aceptable en ejemplos pequeños. En aplicaciones reales, no lo es tanto.
localStorage vs sessionStorage: diferencias que sí importan
Ambos comparten casi todas las limitaciones. La diferencia principal es la duración. Ninguno resuelve problemas modernos como concurrencia, datos estructurados o rendimiento bajo carga.
El gran problema de localStorage: solo almacena cadenas
Este es el origen de muchos errores silenciosos.
localStorage no entiende objetos, arrays ni tipos. Todo pasa por serialización manual. Y aquí empiezan los bugs.
Serialización y deserialización: el origen de bugs silenciosos
En mi experiencia, una cantidad sorprendente de estados corruptos en producción venían de una mala gestión de JSON.stringify() y JSON.parse().
Valores como "true", "false", "null", "" o incluso datos mal versionados acaban provocando comportamientos impredecibles. El resultado suele ser el mismo:
“borra la caché y vuelve a intentarlo”.
Como cliente, el último año tres servicios distintos me dieron exactamente esa solución. No era magia: era localStorage mal gestionado.
localStorage no usa datos estructurados (y eso lo deja en el pasado)
JavaScript moderno usa el algoritmo StructuredClone para transferir datos de forma segura y consistente.
APIs como:
- IndexedDB
- Web Workers
- postMessage
- Cache API
- BroadcastChannel
usan datos estructurados sin serialización manual.
localStorage no.
Cuando trabajas con estas APIs modernas y vuelves a localStorage, se siente como retroceder una década. Y lo peor: no hay planes para actualizarlo.
Problemas reales de seguridad con localStorage
Esto no es teoría. Es práctica habitual… y peligrosa.
Por qué nunca deberías guardar tokens, JWT o sesiones
He visto demasiadas veces:
- JWT
- IDs de sesión
- claves API
guardadas en localStorage “porque es fácil”.
localStorage es accesible desde cualquier script que se ejecute en tu página. Un XSS es suficiente para exfiltrar todo. Y como los datos son persistentes, el impacto se multiplica.
Nunca deberías almacenar datos sensibles en localStorage.
Rendimiento y bloqueo del hilo principal
localStorage es síncrono. Cada lectura y escritura bloquea el main thread.
Operaciones síncronas y su impacto en la UX
En aplicaciones con estado frecuente, esto afecta directamente a:
- animaciones
- scroll
- interacción del usuario
En dispositivos de baja potencia, el problema se agrava. He visto interfaces entrecortadas simplemente por leer y escribir demasiado en localStorage.
La asincronía no es un lujo. Es un requisito para aplicaciones fluidas.
Limitaciones estructurales: concurrencia, atomicidad y escalabilidad
localStorage:
- No tiene transacciones
- No garantiza atomicidad
- No ofrece aislamiento
- No tiene mecanismos de bloqueo
localStorage y la imposibilidad de usar Web Workers
No puedes acceder a localStorage desde Web Workers. Eso lo deja fuera de cualquier estrategia seria de concurrencia.
No está diseñado para escalar. Y nunca lo estuvo.
Límites de almacenamiento y gestión del ciclo de vida de los datos
El famoso límite de ~5 MB sigue siendo real (y variable según navegador).
El límite real de localStorage (y el riesgo de desalojo)
Ese espacio es:
- pequeño para apps modernas
- sujeto a desalojo
- responsabilidad tuya de gestionar
El navegador no te avisa. Tú debes manejar fallos, limpieza y recuperación. Cosa que casi nadie hace bien.
Breve historia del almacenamiento en el navegador: cookies, WebSQL y errores repetidos
Antes de localStorage, tuvimos cookies. Luego WebSQL.
Por qué WebSQL murió
- Implementación limitada a pocos navegadores
- Falta de estandarización W3C
- Competencia directa con IndexedDB
- Preocupaciones de seguridad
WebSQL fue muy querido… y aun así murió.
El paralelismo con localStorage es evidente: tecnología popular, cómoda, pero mal alineada con el futuro.
Por qué IndexedDB es una alternativa real a localStorage
IndexedDB no es perfecto. Pero resuelve los problemas importantes.
Almacenamiento asíncrono y datos estructurados
- API asíncrona (no bloquea el hilo)
- Datos estructurados (StructuredClone)
- Cuotas mucho mayores
- Mayor fiabilidad
No porque IndexedDB sea perfecto, sino porque encaja con cómo funcionan hoy las aplicaciones web.
La API de IndexedDB es mala (pero el concepto es correcto)
Seamos honestos: la API nativa de IndexedDB es incómoda, basada en eventos y verbosa.
Por eso tiene sentido usar librerías ligeras.
Por qué usar una librería ligera tiene sentido
Las buenas librerías:
- usan Promesas
- reducen código repetitivo
- evitan errores comunes
Personalmente, no recomiendo librerías enormes. Para muchos casos, no necesitas versionado complejo ni cursores avanzados. Incluso creé una pequeña librería enfocada solo en lo esencial, porque la mayoría de soluciones estaban sobredimensionadas.
¿Cuándo sí tiene sentido usar localStorage?
Para ser justos: sí hay casos válidos.
Casos simples donde localStorage no es un problema
- flags de UI
- preferencias no críticas
- datos triviales sin impacto en seguridad o rendimiento
Lo que nunca deberías guardar, ni siquiera “por comodidad”
- tokens
- sesiones
- estado complejo
- datos que afectan lógica crítica
Ahí, localStorage deja de ser una solución simple y se convierte en deuda técnica.
Conclusión: localStorage no es el futuro del almacenamiento en JavaScript
localStorage sigue enseñándose porque es fácil de explicar.
Pero facilidad no equivale a buena arquitectura.
Los nuevos desarrolladores ganan mucho más aprendiendo:
- asincronía
- Promises
- datos estructurados
- IndexedDB
que intentando entender por qué "0" rompe una condición o por qué un usuario obtiene datos nulos después de una actualización.
Si hoy puedes evitar localStorage, hazlo.
And if you can't, at least use it knowing exactly what sacrifices you are making.
Preguntas frecuentes sobre localStorage en JavaScript (FAQ)
¿localStorage es seguro?
No para datos sensibles. Es vulnerable a XSS y accesible desde cualquier script.
¿Cuánto espacio permite localStorage?
Aproximadamente 5 MB, dependiendo del navegador, y sujeto a desalojo.
¿localStorage es síncrono o asíncrono?
Es completamente síncrono y bloquea el hilo principal.
¿IndexedDB reemplaza a localStorage?
Para la mayoría de aplicaciones modernas, sí debería hacerlo.
¿localStorage bloquea el main thread?
Sí. Cada operación de lectura y escritura.
Comparativa Técnica: localStorage vs. IndexedDB
| Característica | localStorage | IndexedDB |
|---|---|---|
| Tipo de Datos | Solo Strings (UTF-16) | Objetos, Blobs, Arrays, etc. |
| Capacidad | ~5 MB (rígido) | % del disco (dinámico, mucho mayor) |
| Modo de Operación | Síncrono (Bloquea UI) | Asíncrono (No bloquea) |
| Seguridad (XSS) | Muy vulnerable | Vulnerable (pero permite aislamiento) |
| Web Workers | No disponible | Compatible |
| Transacciones | No | Sí (Garantiza integridad) |
Acepto recibir anuncios de interes sobre este Blog.
Descubre por qué esta API síncrona está dañando el rendimiento y la seguridad de tus aplicaciones web modernas. Analizamos sus riesgos frente a IndexedDB y cómo gestionar datos estructurados correctamente en JavaScript.