Es habitual tratar la eliminación de cuenta como una funcionalidad menor, algo que se añade al final del desarrollo porque "total, es solo un botón que borra datos". Al planificar cómo funcionará el sistema de cuentas en el proyecto de Caladero de cara al futuro, y pensando también en los requisitos que exigirá FishMind cuando llegue el momento de completar su validación, he llegado a la conclusión contraria: cuanto antes se piense en cómo se elimina una cuenta, menos trabajo de rediseño hace falta más adelante.
Por qué esta funcionalidad es más compleja de lo que parece
Eliminar una cuenta no es solo borrar una fila de una tabla de usuarios. En cualquier app con cierta complejidad, los datos de un usuario suelen estar distribuidos en varias tablas o colecciones relacionadas: perfil, contenido creado, preferencias, registros de actividad, posibles copias en sistemas de caché o de backup. Si el modelo de datos no se diseñó pensando en que algún día habrá que borrar todo eso de forma coherente, la implementación de la eliminación de cuenta se convierte en una tarea de arqueología: hay que repasar todo el esquema de datos buscando cualquier tabla que pueda contener algo asociado a ese usuario, con el riesgo real de olvidar alguna.
Por qué Google Play lo exige de forma explícita
Google Play requiere que las apps que permiten crear una cuenta ofrezcan también una vía clara para solicitar su eliminación, tanto desde dentro de la propia app como, en muchos casos, desde un recurso accesible sin necesidad de tener la app instalada, como una página web. La documentación oficial detalla este requisito en support.google.com. No basta con permitir "cerrar sesión" o "desactivar temporalmente"; el requisito habla explícitamente de eliminación real de los datos asociados a la cuenta, no de una desactivación reversible disfrazada de eliminación.
Diseñar el modelo de datos pensando en el borrado desde el principio
La forma más eficaz que he encontrado de evitar el problema de "arqueología de datos" es diseñar, desde el principio, todas las tablas o colecciones que dependen de un usuario con una relación explícita y clara hacia ese usuario, en vez de relaciones implícitas o indirectas. En una base de datos relacional, esto significa usar claves foráneas con borrado en cascada (ON DELETE CASCADE) allí donde tiene sentido que el dato desaparezca junto con la cuenta:
CREATE TABLE puntos_guardados (
id UUID PRIMARY KEY,
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
nombre TEXT NOT NULL,
ubicacion GEOGRAPHY(POINT, 4326)
);
Con esta relación definida desde el principio, eliminar un usuario de la tabla usuarios elimina automáticamente todos sus puntos guardados asociados, sin necesidad de escribir lógica adicional dispersa por distintas partes del código para borrar cada tabla relacionada manualmente. Si esta relación no se define hasta que hace falta implementar la eliminación de cuenta, hay que revisar todo el esquema ya existente y añadir estas relaciones de forma retroactiva, con el riesgo de que alguna tabla quede fuera de ese repaso.
Qué pasa con los datos que no se pueden borrar de inmediato
No todos los datos asociados a un usuario se pueden ni se deben borrar de forma instantánea. Puede haber registros que, por motivos legales o de auditoría, deban conservarse durante un periodo determinado, o copias de seguridad que no se pueden purgar de inmediato sin afectar a la integridad de backups recientes. Una eliminación de cuenta bien diseñada distingue entre lo que se borra de inmediato y lo que se anonimiza o queda marcado para un borrado diferido, y esa distinción se explica también en la política de privacidad, como comento en el artículo sobre qué debe explicar la política de privacidad de una app Android.
Un ejemplo de cómo lo plantearía en el flujo de la app
Aunque Caladero todavía no tiene un sistema de cuentas centralizado en producción, el diseño que tengo previsto para cuando llegue ese momento sigue un flujo claro:
- El usuario accede a la opción de "Eliminar cuenta" desde los ajustes de la app, sin tener que buscarla escondida entre varias pantallas.
- Se muestra una confirmación explícita, indicando qué se va a borrar y qué no se puede deshacer, sin lenguaje ambiguo.
- Al confirmar, se inicia el proceso de eliminación en el backend, marcando la cuenta y sus datos asociados según lo que corresponda: borrado inmediato para la mayoría de datos, anonimización o borrado diferido para lo que tenga alguna razón legítima de conservación temporal.
- Se informa al usuario de que la solicitud se ha procesado, y si hay algún dato con borrado diferido, se explica el plazo aproximado.
Este flujo se diseña en el papel antes de escribir ninguna línea de código de la funcionalidad de cuentas, precisamente porque las decisiones tomadas en el modelo de datos inicial (qué se relaciona con qué, con qué tipo de borrado) son mucho más baratas de tomar antes de que existan datos reales de usuarios que después.
Errores habituales al implementar esta funcionalidad
Un error frecuente es implementar la eliminación de cuenta como un simple cambio de estado ("cuenta desactivada") sin borrar realmente los datos subyacentes, presentándolo de cara al usuario como una eliminación completa cuando en realidad no lo es. Esto no solo es problemático desde el punto de vista de cumplimiento, es directamente una falta de honestidad hacia quien confió sus datos a la app.
Otro error es no probar el flujo de eliminación con datos realistas antes de publicar la funcionalidad. Es fácil probar la eliminación de una cuenta recién creada sin apenas datos asociados y dar por buena la funcionalidad, sin comprobar qué pasa cuando esa cuenta tiene meses de actividad, fotos guardadas, puntos marcados y preferencias configuradas. Los problemas de relaciones de datos olvidadas suelen aparecer precisamente con cuentas que tienen un historial de uso real, no con cuentas de prueba vacías.
Un tercer error, más sutil, es no gestionar bien las referencias cruzadas cuando el dato de un usuario es visible o relevante para otros usuarios, algo que no aplica todavía a Caladero en su estado actual pero que sí habría que considerar si en el futuro existiera algún tipo de contenido compartido entre usuarios: hay que decidir con antelación qué pasa con ese contenido compartido cuando el usuario que lo creó elimina su cuenta, en vez de descubrir el problema cuando ya ha ocurrido en producción.
Conclusión
La eliminación de cuenta no es una funcionalidad menor que se puede improvisar al final del desarrollo. Es una prueba de estrés real del modelo de datos completo de una aplicación: obliga a tener claro, en todo momento, qué datos pertenecen a un usuario y cómo se relacionan entre sí. Diseñar esas relaciones desde el principio, antes de que existan datos reales de usuarios que complicar, es mucho más barato que reconstruirlas después bajo la presión de un requisito de publicación en Google Play. Es, en el fondo, la misma lógica que aplico al resto de decisiones de privacidad del proyecto: pensarlas pronto, no cuando ya es tarde para hacerlo bien.
