Realtime analytics with Go + NATS

Published by Ray Barrera on May 15, 2025

Introduction

In the Brighter platform, the student-facing games and activities generate several events: general interaction events, game events that describe progression (or lack thereof) in a particular game, and engagement events. Individually, these events lack the full context of what the user experienced, and in aggregate, they are too noisy to paint a useful picture. Specifically, we needed a solution to use these events to power insights for our parent and educator monitoring tools and, most importantly, to create a feedback loop for the learning platform to adapt in real time to the student's progression. Let's do a high-level overview of how we have solved this problem.

Initial Findings

In the most generic sense, this is an analytics-shaped problem, so logic would dictate that you turn to off-the-shelf analytics solutions. There are several, like Firebase Analytics, for example, but these are generally designed for business intelligence use cases. Some do offer segmentation and cohorting tools to drive dynamic variables or A/B tests in your applications, but they generally don't provide a way to expose the metrics to your end user, so that rules these solutions out for our use case.

The next logical place to look would be a more general-purpose data platform, like Snowflake or Google Analytics + BigQuery, for example. You can then store, transform, and deliver the data via some flavor of SQL to a visualization tool, like Streamlit. For 99.99% of use cases, this amount of abstraction and complexity (let's not even talk about cost) is overkill. There is a broader philosophical argument to be had here about highly specialized analytics and data disciplines doing routine application work, but we can save that for another time. For now, let's rule these out on technical merits:

  1. Our use case has relatively low cardinality, meaning the number of dimensions we're dealing with is small.
  2. We have full control over the entire data pipeline, including the shape and contents of the data.
  3. Our application needs real-time access to the data, so we need to couple a synchronous process to an asynchronous one.

Looking at our needs through this lens and ruling out more complex or abstracted options allowed us to focus on thinking outside the box to arrive at a potential solution. Enter NATS and NATS JetStream.

Our Solution

You can get all the details about NATS on their website, but the tl;dr is: NATS is a lightweight message bus. JetStream builds on top of NATS (and its key-value store) to add scalable data storage and processing capabilities. I'll let you read the manual for the details, but for now, let's see how NATS features map onto our use case and the data lifecycle more broadly.

Event Sourcing and Ingestion: This is the most basic part of NATS, being a message bus and all. To abstract this away from our applications (the event sources), we deploy a "producer" app, which exposes an HTTP endpoint to send events. There are some basic metadata fields that are required, but generally speaking, the API is simple. The server receives an event, then pipes it into NATS.

Extract-Transform-Load (ETL) and ELT: At present, we deploy a single processor app written in Go that embeds NATS, so it can subscribe to the incoming events. NATS's filtering capabilities allow you to mux or demux the events as needed and/or process them on the spot. Because JetStream is a key-value store under the hood, it's at this stage that we can load the processed events for aggregations into a time-bucketed key.

Because NATS is a distributed system, you have some flexibility here. You can scale horizontally to add more processors to keep your system boundaries clean, or you can scale vertically. Generally speaking, you'll achieve durability via replication, but you can decouple that need from the logical processing of data. Because we've chosen Go for this use case, which provides a concurrency-freindly runtime, you benefit greatly from adding more cores to a single node.

Queries and Analysis: This is perhaps the biggest paradigm shift compared to the status quo. I happen to share Uncle Bob's general disdain for SQL. Because we're using a key-value store, you can just bolt on an API to get the events you care about. I'm partial to the use of the repository pattern, but that's an implementation detail. For use cases with low cardinality, you'd be best served by adding another processor to generate metrics, but if you really need to dig into data across all its dimensions in a very ad-hoc way, then you can always pipe the results or raw events to a columnar database for analysis. In that sense, NATS still provides a ton of value, even if only as a simple distributed event bus.

Prior and ongoing testing shows the ability to easily process thousands of events per second in real time on a very modest compute instance. Some work will be needed to manage storage and backups, but this solution is so cost-efficient that we can easily defer this work until it becomes a problem. The time-bucketing of the metrics gives us an escape hatch to distribute storage if need be.

Conclusion

This solution balances leaning on battle-tested technology (NATS) with a bit of elbow grease in hosting your own compute to create a solution that is not only cheaper but ultimately performs better within the constraints of the project. This won't be a catch-all for every use case. You may sometimes deal with disparate data sources you don't control or have to do analytics on high-cardinality datasets. This solution would be fairly unpleasant to make work once you get into the hundreds of thousands of columns. So, is this something you should try? Maybe! Working with NATS is the easy part—you'll need to decide what your tolerance is for managing your own infrastructure. Even then, you may be willing to use Synadia Cloud (Synadia is the primary maintainer of the NATS project) and let them handle the NATS side of things. If you want to learn more about NATS, check out the Synadia YouTube channel—they have fantastic learning resources. As of this writing, Brighter isn't quite ready for launch, but if you're curious to follow the product, keep an eye on the Brighter website. That's all for now ✌️


Less Is Powerful

Published by Ray Barrera on August 15, 2024

I'm not just saying "Less is more". I'm saying Less is sometimes just less, and that's OK.

Sometimes, Less gives you the clarity to see what's important.

Less can help shine a light on the hidden gems.

At worst, Less can help you truly understand what you need more of.

 


Tokyo

Published by Ray Barrera on June 3, 2024

Someplace in Tokyo...


The Agile-Industrial Complex

Published by Ray Barrera on May 8, 2024

The agile manifesto focused on four core values: 

"Individuals and interactions over processes and tools

Working software over comprehensive documentation

Customer collaboration over contract negotiation

Responding to change over following a plan."

It was a simple mantra, and easy for teams to understand, at least in principle. There is no mention of sticky notes, no rules about what meetings to have when and with whom, and no talk about mob or pair programming–just four simple values.

As the industry around software engineering has matured, so too have the processes that drive software development from the ideation phase to delivering a product or service to an end user. This process of maturation has invited many to look at every step of the software development life cycle to eke out every possible optimization. Not just in terms of throughput, but in the increasingly important areas of professional development, developer satisfaction, etc.

Devs 💖 frameworks

The combination of simple values teams could rally around and a love of systems, naturally lead to an attempt to build frameworks that teams could implement. Not just vague idealistic principles, but actionable plans and roles that teams could wrap their heads around. 

I’m not just referring to [insert JavaScript framework of the week here]. Along with this agile awakening, we have seen the proliferation of agile frameworks to help teams of any scale implement “agile principles” into their process. No two tech companies are the same–they range from a few individuals to several thousand. Some are public, others are private. Some specialize in highly regulated industries like finance and healthcare. It is against this background that we’ve seen a variety of agile frameworks proliferate. The number of acronyms describing these frameworks will make your head spin–SAFe, XP, LSD, DA, etc.

All that said, you’ve likely heard of at least two frameworks that dominate the landscape: Scrum and Kanban. If you’re in tech, there’s a good chance you’ve at least one of them….

Or at least something you heard referred to by the same name. 

Market Opportunity 💰 

To satisfy the demand for process sanity in growing organizations, an entire industry has sprung up–legions of agile trainers, promising to make your process woes a thing of the past. There are mountains of books on the topic, and no shortage of gurus willing to help teach your organization the agile way… for a handsome fee. In the VC-powered land of tech and software, there is no shortage of opportunity for building an entire career out of training and coaching teams on agile.

The demand for these coaching services has grown, but the supply of true experts in the field software engineering that actually know how to grow organizations and help build teams that work efficiently has not kept up with the demand. True expertise takes time, dedication, and effort to develop. In order to bridge the gap, the industry has tried to fill in the gaps, and build shortcuts. Training programs and certifications that you can complete in days or weeks are readily available… for a handsome fee. And just like that, you can become a bonafide agile expert without ever having led a team successfully.

The shrewdest of the bunch, have found ways not just to fill the gaps in demand, but to invent all-new niches within the industry. And with each “invention”, or layer of training on top of the core concepts, we get farther and farther from what Agile was meant to be.

Post-Agile Wasteland ☣️

For those lucky enough to find the pockets of true expertise in the industry, and to match them with leaders within organizations that effect true, radical change, the benefits of agile are immediate, obvious, and profound.

All too often, unfortunately, engineering teams are left with a sour taste in their mouths after failed transformations, or ineffective implementations of agile frameworks that miss the mark. If I had a penny for every time I’ve interviewed an engineer whose understanding of agile was “I have stand ups, and use JIRA to manage tasks”, I might be able to afford one of these fancy scrum training programs. This ambivalence towards scrum is, of course, the best-case scenario.

Worse yet, are teams or engineers that are completely allergic to even the mention of scrum or agile because they’ve been stuck in hours and hours of planning meetings where no one understands why they are there, why they are playing poker games with funny numbers, and why the designer in the room is falling asleep in the back of the room.

The lack of deep, shared understanding of why the team is doing the things they are doing, inevitably leads to a lack of caring for any of the things they are doing. They’ll do them to get them done, not because they add any value.

The Pitch 🎤

This is the part where I pitch you on my podcast, newsletter, training program, book, or consulting company that will solve all of these problems. It’s the part where I say something like “I can help you avoid these pitfalls… for a handsome fee.” But the reality is that there are no shortcuts. Leaders in organizations that want to improve and grow must recognize that there is no substitute for the hard work. This is what separates successful teams from those that are destined to fail.

Becoming an Agile team that understands the fundamental purpose of the methodology requires deep understanding of what success looks like, a willingness to learn, the application of expertise and a desire to implement a culture of craftsmanship in your organization. Yes, there is a place for trainers, training programs, books, and all of it, but none of these can be a cure-all for your team. Be very skeptical of any individual trying to sell you on a magic remedy. Your engineering team will be.


This is a test post

Published by Ray Barrera on April 22, 2024

Hey, look at that! The new blog works :)