21Factory is based in Paris at Station F, one of Europe’s largest incubators. Its product, OmniLab, helps marketing teams build interactive experiences such as games, events, 3D, and augmented reality. One notable customer is one of the top commercial real estate companies with more than 50 shopping centers across Europe and the US, where marketing teams use OmniLab.
The backend is written in Go. The frontend uses React and Next.js. Services run on Kubernetes. Synchronous service-to-service communication uses gRPC. MongoDB Atlas is the transactional database. The team uses AWS heavily with Terraform, plus some Google Cloud.
That stack worked. But as OmniLab grew, 21Factory needed a cleaner way to handle downstream work that did not have to happen synchronously. They wanted event-driven microservices, and they did not want to end up operating an event broker as a second product.
21Factory kept gRPC for the paths where one service needs an immediate answer from another. Plenty of other work did not need that. A business event could be published once and picked up by whichever downstream services cared. Webhooks could fire without blocking the producer. Failed events could be moved to a dead letter queue, and internal service work could be decoupled from external request paths.
The goal was to add an event-driven backbone without adding operational drag, because engineering time at 21Factory goes to OmniLab and customer-facing features, not to running a broker.
So 21Factory ran a benchmark. They evaluated open-source Kafka, NATS, and vendor-specific options like SQS against practical criteria:
The shortlist came down to Kafka and NATS. For managed Kafka, they looked at Confluent and Google Cloud. For managed NATS, they looked at Synadia Cloud.
NATS won on simplicity. 21Factory found it easy to learn: the website and docs were clear, and in roughly a day the team understood the three pieces they needed to evaluate, Core NATS, JetStream, and KV. That counted for more than the raw benchmark numbers.
Kafka performed well too, and 21Factory said so. Performance did not decide the evaluation because both cleared the bar. The team confirmed NATS could scale to millions of events, then ranked the remaining factors: simplicity first, cost second, CNCF trust third, and validated performance fourth. NATS being a CNCF project read as a signal of maturity and longevity, since 21Factory already ran other CNCF projects in production.
Ordering was the one nuance. Kafka offers ordering natively through ordering keys and partitions. JetStream preserves the order of messages within a stream, but at the time of 21Factory’s evaluation it did not offer Kafka-style ordered, partition-keyed parallel consumption in the same way. That was not a deal breaker, because strict ordering is not a requirement for their consumers. The team went deep on the NATS model anyway, using subjects and wildcards to implement their own approach to partitioning.
NATS gave 21Factory the patterns they needed, with less to learn and less to operate.
21Factory could have dropped an open-source broker into Kubernetes. Kafka and NATS both made that possible. They chose not to, because they wanted to pay for the broker as infrastructure and keep their engineering focus on OmniLab.
That made the managed-service comparison the final decision. Synadia Cloud was the most cost-competitive option, especially on the plan 21Factory landed on, and cost was a real factor in the call. NATS gave the team a simple eventing model, and Synadia Cloud gave them managed NATS without the self-hosting burden.
21Factory uses an outbox pattern. When a producing microservice writes to MongoDB, it also writes to an outbox collection in the same transaction. That keeps the business write and the event record together and avoids the dual-write problem, where a database update succeeds but event delivery fails, or the reverse.
From there, 21Factory uses Debezium server, not Kafka Connect. Debezium watches the MongoDB change data capture stream on the outbox collection and publishes events to NATS JetStream. JetStream is the event broker. Downstream consumers subscribe and process events as they are published.
The flow looks like this:
Producers never manage delivery logic directly.
21Factory runs a main business stream that carries business events across the system, a dead letter queue stream where failed or unprocessable events go for separate handling, and per-service streams that individual microservices use for their own internal asynchronous work.
That last use is easy to overlook. JetStream is the central event broker, and it is also a service-local async primitive. The webhook service reacts to events published by business producers, then triggers an outbound HTTP call to any API. Internally, it uses its own JetStream stream to decouple that work.
So one technology covers central business event distribution, durable streams, dead letter handling, internal service decoupling, and asynchronous webhook execution. The team did not need to assemble a larger stack of moving parts to cover these patterns.
OmniLab users never see the infrastructure. Marketers use OmniLab Studio, the back office, to build interactive campaigns, and visitors encounter those campaigns across channels.
For a major AAA movie production around December, that customer used OmniLab at one of its London shopping centers to run a ticketing experience and an augmented reality treasure hunt. Visitors collected tokens themed to the movie’s universe. The campaign involved roughly 40,000 tickets. Visitors arrived through the shopping center’s website, TikTok and Instagram posts, or email, and in the shopping center they scanned QR codes for the AR treasure hunt.
A campaign like that is high-traffic and time-boxed. Tickets, visitor actions, and downstream work have to move through the system while the experience stays responsive. The event-driven backbone is what makes that work: producers and consumers stay decoupled, downstream work happens asynchronously, and failed events have somewhere to go.
NATS gave 21Factory the eventing patterns they needed. Synadia Cloud runs it for them at a price that fit their cost requirement. Engineering time stayed on OmniLab.
Meet with our architects to get help tailored to your use case and environment.



News and content from across the community