ecosystem-wikicómo extender los templates sin romper sus convenciones
‹ todo el contenido

Tokens de push muertos

notification-worker
último cambio 2026-09-25

Un token de push muere cuando se desinstala la app, se limpian los datos o FCM lo rota. A partir de ahí no vuelve a servir jamás, y quien lo guarda no es este stack: lo guarda el producto, en su tabla de dispositivos.

De ahí el único flujo que va del worker hacia atrás, hacia quien le pidió el envío.

FCM rechaza un token
   → FcmProvider lo devuelve en deadRecipients
   → DeadTokenCallbackService hace POST al producto
   → petid-api purga la fila del dispositivo

Rechazado no es lo mismo que muerto

DeliveryResult distingue dos listas y el processor las trata distinto:

Campo Qué significa Qué provoca
failedRecipients Cualquier fallo, con su errorCode si lo hay La fila del log pasa a FAILED
deadRecipients FCM confirma que es permanentemente inválido Además, se avisa al producto para que lo borre

El comentario del processor lo resume: cualquier respuesta no exitosa es un fallo real; solo los tokens que FCM confirma muertos se purgan además vía el callback. Un fallo de red no debe borrar el dispositivo de nadie.

El callback

POST {API_BASE_URL}/webhooks/push/dead-tokens, con x-webhook-secret y 10 segundos de tiempo límite. Del otro lado, ese endpoint de petid-api valida el secreto compartido —FCM_CLEANER_WEBHOOK_SECRET, mismo nombre literal en los dos repos— y purga los tokens.

Es deliberadamente best-effort: si falta la configuración, o el producto responde un error, o la llamada revienta, se registra un warn o un error y ya está. El push ya se entregó a los tokens vivos; que la limpieza falle no debe tumbar el trabajo.

La consecuencia de que sea best-effort: los tokens muertos se acumulan en silencio si el callback lleva tiempo roto. No hay reintento ni cola de pendientes. El síntoma es una tabla de dispositivos que crece y envíos que fallan contra tokens que hace meses que no existen — y el rastro está en los logs del worker, no en los del producto.

Si no está configurado

Con API_BASE_URL o FCM_CLEANER_WEBHOOK_SECRET sin poner, el servicio ni lo intenta y deja un warn diciendo cuántos tokens se quedaron sin purgar. Es la señal a buscar si sospechas que la limpieza no está corriendo.

Del lado del producto hay un espejo de esto: si a petid-api le falta su FCM_CLEANER_WEBHOOK_SECRET, el arranque no falla, pero el guard del webhook responde 401 siempre. Los dos extremos degradan en silencio por separado, así que conviene comprobarlos a la vez.