Creating a web app notification system/center? Ok, just thinking out loud and trying to work out the best way to achieve something. I have a community site with roughly 25k users. 

I would like to create a way to send messages to those users within the front end of the site. This might be, for example, a notification of a new entry based on a set of criteria or even a message from the site admin to every user advising of a new feature.

The user should be able to view the message, which marks it as read and have the ability to delete it. All messages would live in a notifications page.

I’m just wondering if this is something that’s possible to achieve using Craft (via a plugin) or are there other services that are better suited to this. I can’t find anything online, everything seems geared towards push notifications which is slightly different to what I’m after.

Any thoughts as I can’t quite get my head around a way to achieve this.

Thanks!
I created a simple plugin for you to start. Note that is not a ready-to-use plugin so you'll have to change the things you need. This is just meant to be a starting point for you.
You can use the code and change it how you like it but mostly it is for learning purposes. So please don't expect it to be "finished" since I don't know your needs and your structure. The most important thing: my css/design skills are awful so I did not style anything.. you have to do it on your own

Feel free to say what I could/should change for you.

So here it is Usernotifications

So let's go through it:
My idea was to create a section called usernotifications (you don't have to do it by yourself, it is created onAfterInstall and can be changed later) that has different entry types for different messages and purposes. If you want to change the section handle make sure to change the $criteria-&gt;section = 'usernotifications'; in my service. This way you can create messages/notifications how you like and make them really dynamic. Please read this for some ideas and instructions Overview

Craft renders all those entries unless the user dismisses them or if they are too old. Check my service for the logic.

The Controller:has two methods, the first is actionRemoveNotificationto remove a message/notification for a user. So you'll display a dismiss button and as soon as someone clicks it, you create a record in your database with the userId and the entryId, so you know which user removed a notification. 

/**
 * Remove a notification for a user 
 */
public function actionRemoveNotification(){
    $this-&gt;requirePostRequest();
    $this-&gt;requireAjaxRequest();

    $response = [
        'success'   =&gt; false,
        'message'   =&gt; 'could not find entry'
    ];
    if($entryId = craft()-&gt;request-&gt;getParam('id')){
        $userId = craft()-&gt;userSession-&gt;getUser()-&gt;id;

        $record = UsernotificationsRecord::model()-&gt;find('entryId = :entryId AND userId = :userId', array(
            'entryId'   =&gt; $entryId,
            'userId'    =&gt; $userId
        ));
        if($record){
            // user already removed the message... there must be something wrong or he/ she cheated :P
            // you can actually ignore this... just wanted to show you how to search for entries^^
        }else{
            $record  = new UsernotificationsRecord();
        }

        $record-&gt;userId = $userId;
        $record-&gt;entryId = $entryId;

        if($record-&gt;save()){
            $response['success'] = true;
            $response['message'] = 'notification removed for user';
         }else{
            $response['message'] = 'could not save record';
            $response['errors'] = $record-&gt;getErrors();
        }
    }

    $this-&gt;returnJson($response);
}


The service: 
The service should return all notifications for the current User or nothing at all if the user is not logged in

/**
 * Get all notifications for the current user
 *
 * @return string
 */
public function getAllNotificationsForUser(){
    // check if user is logged in...
    if(!craft()-&gt;userSession-&gt;getUser()){
        return false;
    }

    // fetch all removed notifications of the user to not fetch them in our query
    $removedNotifications = craft()-&gt;db-&gt;createCommand()
        -&gt;select('entryId')
        -&gt;from('usernotifications')
        -&gt;where(['userId' =&gt; craft()-&gt;userSession-&gt;getUser()-&gt;id])
        -&gt;queryColumn();

    $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Entry);
    $criteria-&gt;section = 'usernotifications';
    // user should not be overwhelmed with too many notification when they didn't log in for too long
    // so show only notifications 14 days ago, you can change this length or remove it if you want
    // but make sure to change the value in the task as well.
    // you could also create settings for the plugin where you can store how long
    // then entries should be displayed
    $someDateInThePast = date('U', strtotime("-14 days"));

    $criteria-&gt;postDate = "&gt; " . $someDateInThePast;
    // exclude the ids of the removed notifications
    if($removedNotifications){
        $criteria-&gt;id = 'and, not ' . implode(', not ', $removedNotifications);
    }

    return $criteria-&gt;find();
}


Your Variable
In your variable you'll get the html for those notifications, you can find the templates in templates/entries/entrytypes

public function getAllNotificationsForUser(){
    $html = '';
    $entries = craft()-&gt;usernotifications-&gt;getAllNotificationsForUser();
    if($entries){
        // I get a deprecated hint here, but the solution stated in craft throws
        // an exception... So I'm using this one
        $oldPath = craft()-&gt;path-&gt;getTemplatesPath();
        $newPath = craft()-&gt;path-&gt;getPluginsPath() . 'usernotifications/templates';
        craft()-&gt;path-&gt;setTemplatesPath($newPath);
        $html = craft()-&gt;templates-&gt;render('entries/index.twig', array(
            'entries' =&gt; $entries
        ));
        craft()-&gt;path-&gt;setTemplatesPath($oldPath);
    }
    return $html;
}


I guess these are the most important parts, you can check the rest in my git repo and ask/request whatever you like.

You can render the entries with 

{% set notifications = craft.usernotifications.getAllNotificationsForUser() %}
{{ notifications|raw }}


Before I forget it: I created a task to remove too old records. You can access it via /admin/actions/usernotifications/removeOldRecords