🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 8 Min Lesezeit
0

From 30-Second Polling to Real Push Notifications

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

This article was originally published on + @Transactional Trap


This one nearly cost us a day.



Our push delivery runs inside @Async methods. When a token needs to be soft-deleted (delivery failure), we need a database transaction. The natural instinct is to extract a @Transactional private method.



This does not work.



Spring's @Transactional relies on AOP proxies. When you call a @Transactional method from within the same bean, the call goes through this, not through the proxy. The annotation is silently ignored. Your "transaction" is actually running without one.



Inside an @Async method, you're already past the proxy boundary. Internal calls to @Transactional methods are no-ops.



The fix: TransactionTemplate. Programmatic transaction management that works regardless of proxy context.




CODE
void softDeleteToken(UserPushTokenEntity token, String reason) {
transactionTemplate.executeWithoutResult(status -> {
userPushTokenRepository.hardDeleteSoftDeletedByPushToken(token.getPushToken());
token.setDeleted(true);
token.setDeleteReason(reason);
userPushTokenRepository.save(token);
});
}






Not glamorous. But it actually works. Every time.






The Mobile Side: Less Drama, More Plumbing



The React Native side was comparatively calm. A single usePushNotifications hook handles everything:





  1. Permission requestNotifications.getPermissionsAsync() then requestPermissionsAsync() if needed


  2. Token retrievalNotifications.getDevicePushTokenAsync() (native token, not Expo token)


  3. Backend registration — RTK Query mutation, best-effort (silently fails if backend is unreachable)


  4. Foreground handlingsetNotificationHandler to show banners even when the app is open


  5. Cache invalidation — When a push arrives in the foreground, we invalidate RTK Query's UnreadCount cache tag. The NotificationBell re-renders with the fresh count. No polling needed.


  6. Tap routing — When the user taps a notification, we extract actionUrl from the payload data and router.push() to the right screen



The hook stores the push token in a module-level variable (not React state, not Redux). Why? Because during logout, React state may be mid-teardown and Redux may be mid-reset. A simple module variable survives both.






The NotificationBell: From Polling to Push



Before:




CODE
const { data } = useGetUnreadCountQuery(undefined, {
skip: !isAuthenticated,
pollingInterval: 30000, // The sin
});






After:




CODE
const { data, refetch } = useGetUnreadCountQuery(undefined, {
skip: !isAuthenticated,
// No polling. Push notifications invalidate the cache.
});

// Only refetch when user returns to the app (tab switch, unlock)
useEffect(() => {
const sub = AppState.addEventListener('change', (next) => {
if (appState.current !== 'active' && next === 'active' && isAuthenticated) {
refetch();
}
appState.current = next;
});
return () => sub.remove();
}, [isAuthenticated, refetch]);






The difference: from 2,880 requests/day to maybe 20-30 (one per app foreground event). Server load dropped. Battery usage dropped. And notifications arrive instantly instead of up to 30 seconds late.






What We Shipped
















































Aspect Before After
Delivery mechanism HTTP polling (30s) FCM (Android) + APNs (iOS)
Background delivery None Full system-level push
Latency 0-30 seconds Sub-second
Requests per user/day ~2,880 ~20-30
Third-party dependency None None (direct to Apple/Google)
Token management N/A Auto-cleanup on delivery failure
Foreground behavior Badge update on next poll Instant banner + badge + sound





Lessons Learned





  • Expo Push Service is good. Direct is better. If you're serious about push reliability and payload control, go direct. The implementation cost is a few hundred lines of JWT plumbing.


  • @Async and @Transactional don't compose. Use TransactionTemplate for programmatic transactions inside async methods. This isn't a Spring bug — it's how AOP proxies work.


  • Soft-delete + unique constraints need careful choreography. Partial unique indexes (WHERE deleted = false) are powerful but require hard-deleting stale soft-deleted rows before creating new ones.


  • Store push tokens outside React state for logout. Module-level variables are ugly but survive the teardown chaos of a logout flow.


  • getDevicePushTokenAsync > getExpoPushTokenAsync if you're doing direct FCM/APNs. Skip the Expo token abstraction layer.


  • HTTP/2 is mandatory for APNs. Ensure your HTTP client is configured for it explicitly. Silent failures here are painful to debug.






Have you made the polling-to-push jump? What surprised you the most? Drop a comment below.



Building jo4.io — a modern URL shortener with analytics, bio pages, and an affiliate marketplace for creators.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten From 30-Second Polling to Real Push Notifications

Thematisch verwandte Begriffe: From, 30Second, Polling, Real · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...