- Topics
- /
- Architectural patterns
- /
- Live multiplayer quiz
Live multiplayer quiz
Multiplayer quizzes are a great way to engage your audience, be it as part of an event or in an EdTech environment. 2020 saw a huge rise in the number of multiplayer quiz applications, allowing people to remotely participate in a live quiz with a host serving them questions and revealing scores as they go.
Regardless if it's a standalone quiz like Kahoot, or one that is integrated into your slide deck, like Mentimeter, the underlying technology behind these apps is similar and relies heavily on realtime messaging architectures. Some of the popular products which offer multiplayer quizzes are listed below:
In this article, we’ll look at the high-level architecture required to build these multiplayer quiz apps and specifically explore the realtime message flow and implementation.
Fundamental realtime features in a multiplayer quiz app
While each product puts a unique spin on their multiplayer quiz offering, we can assume some common realtime features:
1. The concept of host and participants. The host is generally the curator of the quiz questions and runs the live quiz for participants to engage with. The participants log into the specific quiz using an invite link. Once in, they see the questions appear on their devices with options to register their answers.
2. Live scores and leaderboards. As participants answer the questions, they get scored based on accuracy and any other factors, such as time-to-answer. Based on the answers registered by a player, the host and the other participants can see the leaderboard updating with live scores.
3. Synchronized timer. Each question has a limited amount of time within which the participants are required to choose an answer. This timer needs to run in sync for all the participants to ensure fair play.
4. Being aware of peers. As these are mostly competitive quizzes, participants need to know how many people are playing alongside them and who they are. So, it is necessary to know the online status changes of all the participants.
Architecture
In this section, we’ll see some architectural patterns to build a live multiplayer quiz app. We’ll first understand it from the perspective of a popular infrastructure provider, Amazon Web Services (AWS). We’ll see an example multiplayer quiz architecture implemented entirely over AWS then replace some parts with Ably’s realtime messaging infrastructure to demonstrate how Ably can remove realtime complexity.
A simplified view of the system that runs a multiplayer quiz for three participants would look like so:
You would have your server publishing the questions, receiving the answers, checking them, and computing the scores. Among the front-end clients, you would have a host controlling the flow of the quiz and participants engaging accordingly.
The most important aspect of this system is how various messages flow between these components. As shown by the two-sided arrows, we need a way for these components to communicate bi-directionally, in a stateful manner, possibly at high frequency.
Ably in a nutshell
Ably provides APIs to implement pub/sub messaging for the realtime features in your apps. You also get a globally-distributed scalable infrastructure out-of-the-box, along with a suite of services. These include features like presence – which shows the online/offline status of various participants, automatic reconnection and resumption of messages in case of intermittent network issues, message ordering and guaranteed delivery and easy ways to integrate with third-party APIs.
Ably enables pub/sub messaging, primarily over WebSockets. The concept of channels allows you to categorize the data and decide which components have access to which channels. You can also specify capabilities for various participants on these channels like publish-only, subscribe-only, message history, etc.
Let’s begin by seeing an example multiplayer quiz architecture implemented entirely on AWS, as it is a popular infrastructure provider, then replace some parts with Ably Realtime messaging infrastructure.
Multiplayer quiz architecture with AWS (single region)
Among the plethora of web services offered by Amazon, we’d need roughly the following components to run a live quiz globally, at scale.
Let’s break it down.
The AWS services are highlighted in the explanation below.
We already saw the front-end clients for this example – a quiz host with three participants. They need to communicate with the backend server. In this case, we can assume the server-side logic to be hosted on auto-scaling EC2 instances behind a load balancer.
Our front-end clients can access the quiz app via Route53 and Cloudfront, before reaching the Elastic load balancer that decides which out of the available EC2 instances would serve this request.
The backend VPC also communicates with the storage, i.e., S3 buckets and DynamoDB, to store and retrieve various pieces of information and assets.
We also have some Lambda Functions that will be triggered at different points in the server-side logic of the quiz. If our front-end clients also need to access the Lambda functions, they can do so via the API gateway.
This is fine for REST-based communication, which works based on stateless request/ response cycles. As we discussed before, what we need in addition to this is Pub/Sub based realtime communication capabilities. To enable this with Amazon Web Services, we’ll need an Elasticache for Redis to serve as a global datastore with Pub/Sub messaging capabilities. Our backend servers hosted as EC2 instances will stay in-sync with various updates within sub-250-millisecond latencies via this Redis cache.
To enable scalable Pub/Sub for our front-end clients, AWS recommends using the IoT core service, which enables WebSockets over the MQTT protocol. You also need an authentication mechanism for the front-end clients to securely reach the IoT core. The Cognito service helps with this aspect.
While this enables app-based pub/sub messaging with the backend services, we’d still need something like SNS (Simple Notification Service) to push updates even when the app is not in use. This could be a mobile push notification to let our players know that a new quiz is starting, an email alert, etc. If we’d like to know the online status of the front-end clients, we’d need to implement that logic ourselves and publish messages when different events such as internet failures or app closures occur.
Let’s now see how we can minimize efforts by using Ably to provide realtime communication capabilities.
Multiplayer quiz architecture with Ably
Ably has native features that replace many of the AWS services listed above.
Ably automatically runs in multiple regions globally and internally does all the smart routing without any configuration required by the developer. Ably can also communicate directly (via Pub/Sub and REST) with both backend and front-end services. This does away with the extra work of keeping the scalable backend in sync within itself, then additionally keeping the front-end clients in sync with all of that.
Hence, we can get rid of the Elasticache for Redis, the IoT core, and the API gateway. We can also remove the SNS topics because Ably also provides push notifications and direct integrations with third-party services via webhooks. This reduces a lot of complexity in terms of setting up these services, connecting them up correctly, and maintaining them. Even more so when you add multiple regions as discussed in the next section.
Adding multi-region support for reduced latencies
Let’s go back to the AWS architecture for a second. What we saw earlier was the implementation of these services for a single region. For a live quiz to be hosted globally, you want all the participants to not only be in-sync, but also maintain sub-250-millisecond latencies. This is only possible by ensuring that all clients are routed to a node nearest to them based on their geographic location.
To enable this, we’d need to replicate almost all of the services in multiple regions across the globe. This adds a non-trivial amount of architectural complexity.
Extra maintenance effort and significant configuration and development work are required to ensure these regions are also in sync with each other at all times.
In comparison, Ably makes it much easier to provide low-latency realtime messaging at scale because it is a drop-in replacement for a number of AWS services. We can keep using AWS services to run the backend logic for the quiz, but we no longer need to deal with syncing various components in realtime as we'll be using Ably to do that. In terms of the infrastructure, Ably handles all of the distributed systems challenges including data-sync, availability, smart routing, etc automagically. Developers can access Ably with just a few lines of code irrespective of the scale at which they’d like to run their realtime features.
An example of using the Ably Realtime API to publish and subscribe to messages over channels is shown below:
// API Keys should not be shared. The key here is intended solely for this example.
const realtime = new Ably.Realtime('xVLyHw.OALQ2Q:aQMsViBgfUbTbtk5');
const channel = realtime.channels.get('classroom');
channel.subscribe(function(message) {
alert(`Received: ${message.data}`);
});
channel.publish('example', 'message data');
A close look at channels for multiplayer quiz
If we go back to the first diagram we saw, we can consider any service, AWS or not, to implement our backend. We can enable realtime messaging between any of these components via the Ably platform and connect any other third-party services or applications via webhooks, queues, or Firehose.
For a multiplayer quiz app, here’s how we could use channels:
Let’s understand the above diagram in a bit more depth based on the categories of messages we’d like to stream between various components.
Channel usage
1. The host-admin-ch
channel
This channel is specifically meant for the host to trigger various events on the server like starting the quiz, showing the next question, etc. As you can see, no participants are part of this channel. We would want only the host to have admin rights to trigger such events.
2. The quiz-ch
channel
This channel is the main quiz channel transporting most of the quiz-related data, including new questions, correct answers, or timer tick events.
3. The player-bob-ch
channel
A dedicated channel for Player Bob to publish their answers to the questions in the quiz.
4. The player-lisa-ch
channel
A dedicated channel for Player Lisa to publish their answers to the questions in the quiz.
5. The player-kai-ch
channel
A dedicated channel for Player Kai to publish their answers to the questions in the quiz.
Of course, it's possible to have fewer or more channels, depending on the specifics of your use case. Another option is to have a single channel for all the players to publish their answers and use event names to let the server know which data belongs to which player.
Please note that this is only an architectural pattern. You can use it as a starting point and update the architecture to whatever suits you best.
Have a look at a breakdown of various limits we’ve put in place to allow the Ably platform to be efficiently implemented.
Understanding who is online
The presence feature allows us to see the ‘online/offline’ status of participants. We can use the quiz-ch
channel to manage the presence set as well. All we need to do is have our host and participants enter the presence set as soon as they connect. They’ll automatically disappear from the presence set if they quit the app or get disconnected for a long period due to internet issues. There’s no need to handle this logic yourself separately.
Here’s a quick snippet to show how presence works:
// API Keys should not be shared. The key here is intended solely for this example.
const realtime = new Ably.Realtime({
key: 'xVLyHw.OALQ2Q:aQMsViBgfUbTbtk5',
clientId: 'bob' }
);
const channel = realtime.channels.get('classroom');
channel.presence.subscribe('enter', function(member) {
alert('Member ' + member.clientId + ' entered');
});
channel.presence.enter();
You’ll see in the demo quiz app (linked in the next section) that only the quiz server has subscribed to presence entries and leaves, so it can efficiently manage participants, live stats, scores, and leaderboard. It is possible to have all the components subscribe to presence events as well, but that will lead to an n-squared complexity, making it difficult to scale.
Starter kit and demo
To demonstrate everything discussed so far, we’ve built a starter kit in NodeJS and VueJS by following the architecture explained in this article. You can use it as a starting point and customize it as per your needs or take a look at the open-source project to understand it further and build your own multiplayer quiz from scratch.
This demo implements the worker threads feature in NodeJS to enable multiple quiz rooms, allowing various hosts to simultaneously host their quizzes to groups of participants. Check out the GitHub repo to learn more.
You can also try out the live demo yourself.
Extensions and integrations
You saw a basic architecture that allows you to build a multiplayer quiz app easily. However, in the real world, you may need to add some more components to your system design.
In terms of the realtime messaging architecture, Ably offers a dependable distributed serverless platform that can scale flexibly as needed by various clients. The implementation remains the same irrespective of the scale.
In terms of your product-specific custom architecture, you may want to add other components such as a database, maybe trigger a cloud function to perform some computation, or even stream messages to a third-party service. Ably provides easy ways to integrate with external APIs and services via webhooks, serverless functions, message queues, or event streaming. You can also make use of incoming webhooks to trigger a message on an Ably channel from an external service. (Think of a scenario where you allow participants to answer your quiz via SMS messages!)
Final thoughts
I hope this article gives you a headstart in building live audience engagement features at scale. We’d love to see your multiplayer quiz applications built with Ably, so feel free to Tweet them to us @ablyrealtime.
References and further reading
Building a serverless multi-player game that scales (with AWS)
Building a realtime multiplayer browser game in less than a day (with Ably)
Scale up to a collaborative and multiplayer architecture with edge messaging
Scaling AWS API Gateway WebSocket APIs - what you need to consider
Got questions or concerns? Talk to us, we are always happy to help.
Recommended Articles
Apache Kafka and Ably: Building scalable, dependable chat applications
Learn how Ably complements and extends Kafka to end-users at the edge, enabling you to architect scalable, dependable chat apps.
Maximize the value of realtime analytics with Kafka and Ably
Learn how you can use Kafka and Ably to engineer a high-performance analytics pipeline that connects your backend to end-users at the network edge in realtime.
Scaling Firebase - Practical considerations and limitations
Firebase is used to keep frontend clients and your backend in realtime sync - for example, chat apps, and multiplayer collaboration functionality. But how well does it scale?