Service notifs with Matrix
Tags: matrix, couchdb, microservices, typescript
Published: 2018-04-26 09:59:59

---
title: Service notifs with Matrix
published: true
description: How I simplified our notify infrastructure to a few lines
tags: Matrix, CouchDB, Microservice, Typescript
---

```typescript
import ...

const log = new Log("MatrixProvider")

export class MatrixProvider {
    private client: any;

    constructor(private matrixConfig: any) {
    }

    Setup() {
        this.client = Matrix.createClient({
            baseUrl: this.matrixConfig.homeserver,
            userId: this.matrixConfig.user_id,
            accessToken: this.matrixConfig.access_token
        });
    }

    SendMessage(roomid: string, body: string): Promise<any> {
        return this.client.sendHtmlMessage(roomid, striptags(body), body);
    }
}

```

This is all the code needed to add to our infrastructure to start sending notifications out to staff on the network for alerts. [Matrix] is my first choice when needing to send alerts inside a service. It's quick, it's a single HTTP request and you get push for free! 

## The Problem

The application I am working sends out notifications to 3 groups of people: Admins, Users, and Customers.

- The **admin** needs to find out if requests are repeatedly failing in the backend.
- The **users** need to find out if a customer has filled in a form or sent a review.
- The **customers** need to be notified if there is a change to their assigned products.

The biggest messaging problem I have seen in services I have worked on is that the apps each have their own set of rules for notifying, usually hidden in some config. If you change a group, or a name somewhere you might find yourself rewriting a lot of configuration files -- and that's to say nothing of expandability beyond your standard `sendmail` setup. 

## The Solution

A single service, a single new message queue type and a single mapping document inside our DB.

The service is simple and elegant. It connects to [CouchDB], reads a mapping document and listens for changes (a cool feature of CDB). 

A typical mapping document:
```JSON
{
    "_id":"ccs.notifications",
    "_rev":"xyz",
    "mapping": {
        "#admins": { 
            "matrix": ["!PxMWbvomtRqGOTsaDK:half-shot.uk"],
            "email": ["will@half-shot.uk"]
            "twitter":..,
            "slack":..,
         }
    }
}
```

When a message comes in, we map `content.to` to a mapping field (which must start with a `#`). The mapping is picked up, we traverse and send a notification out one or more rooms. You can then trust the Matrix homeserver to deliver it to the right set of users. Potentially in the future, we may check the status of read receipts to nag the user by email if they have not checked their Riot app.

![Result in Riot](https://thepracticaldev.s3.amazonaws.com/i/9tnfbrqyh86qmn6ayfmq.png)

In the future we could expand on this to include E2E messaging for customers, so they can be sure the message is coming from the correct service and not from an attacker -- should an access token get leaked.

Anyway, this is a quick post about a rather elegant solution to sending notifications.

[Matrix]: https://matrix.org
[CouchDB]: https://couchdb.apache.org/