Because ntfy doesn’t, at least not in a way that detaches you from a central authority.

On its own notification to your device will happen eventually when the ntfy app on your phone wakes up and polls. Pull, not push.

My ntfy server has a config line for an upstream, which is a service that then uses push. Basically it’s self hosted and handing off push.

The default behaviour for self-hosted on Android is to have a foreground service which holds a websocket open, so it does get pushed from the server and doesn't rely on your phone being awake.

https://docs.ntfy.sh/subscribe/phone/#instant-delivery

The upstream approach you describe is only necessary for iOS devices that don't permit apps to do that.

https://docs.ntfy.sh/config/#ios-instant-notifications

On Android the OS implementation of "push" notifications is pull/poll based as well. At some interval, the OS polls Google's servers to see if there are any messages available. Firebase essential acts as a message broker, so that it only has to poll a single server, instead of a separate server for every service that wants to send notifications, and there is only a single service polling.

But I really wish Android supported specifying additional servers to poll (and/or replace the default server), so you could use a self-hosted service in addition to or instead of Google's service.

The difference between ntfy and another type of push is that you don't need a server owned by the group that makes the app forwarding messages through apple or Google. You can have your chat server send messages to your ntfy server, which then arrive on your phone.