1

I have a system that publishes events to a message broker, lets call that system A. I also have system B and system C that subscribes to the "events"/messages.

My payload/message looks like the following:

{
    "eventType":"EntityCreated",
    "entityId": 123,
    "properties": {
        "somedata1": "somevalue1",
        "somedata2": "somevalue2"
    }
}

(This is not how the message really looks.. its just for giving some context to my problem)

Now.. system B is allowed to subscribe and view all events and properties. While system C is not allowed to view any properties given that entityId is NOT 123.

How would this be solved? Im thinking that I might be able to use event sourcing and some sort of auth-mechanic so instead of sending the actual properties over the message, the systems would have to query an api to get an "eventId".. and then that could validate if the system is authorized or not to view the event. But is there any more common pattern/way of doing this? One big drawback with my suggestion would be that if I have many consumers/subscribers, I might end up having a heavy load on that "event sourcing API".

1
  • Why would you send a message to a consumer that isn't authorized to read it?
    – John Wu
    Jul 21, 2022 at 8:00

1 Answer 1

1

This depends on your exact security requirements. Potential solutions:

  • The events are processed by a service that mediates access. Full events are stored in a database. The service then publishes a new event stream that only includes metadata. If a recipient wants to access the body of the message, they ask this service at which point authentication can be checked.

    Drawbacks: data leakage through metadata and rate of messages. Latency for extra communication.

  • The events are processed by a broker/service that copies the messages to event streams matching given filters. Consumers B and C are following different streams.

    Drawbacks: lots of duplication if there are lots of different filters – might need a separate topic for each consumer.

I think that every architecture attempting approach #1 will eventually converge on approach #2: the shared message bus will only notify consumers that new messages might be pending, and then they poll the service A for new messages matching their filters. Such polling is not necessarily problematic from a performance perspective, especially since high-performance message queues like Kafka use a pull-based approach for consumers anyway. This prevents the consumer from being overwhelmed with the rate of messages. The message bus and/or your service A can be scaled/partitioned so that the rate of requests remains manageable.

The main question might be whether the filtering/routing is applied eagerly when a new message arrives, or lazily when the consumer polls for new messages. This depends entirely on the degree of filtering and the access patterns. Lazy filtering is more attractive if all consumers see mostly the same messages. Eager filtering is more attractive if there are few consumers and all their filters are known up front. But in principle, either approach is infinitely scaleable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.