Building a scalable marketplace solution can be a complex challenge, especially when trying to balance performance, customization, and a seamless user experience. In this post, I’ll walk you through the journey of creating a Minimum Viable Product (MVP) for a niche marketplace using Medusa, a powerful and extensible e-commerce framework. From selecting the tech stack to implementing custom features like product offers, messaging, and shipping integration, this guide will dive into the technical decisions and solutions that helped bring the marketplace to life. Whether you're starting from scratch or enhancing an existing platform, these insights will be valuable in your own development process.
Recently, at the company where I work, we faced the challenge of building a marketplace solution that could scale and support vast traffic. It’s for a niche market, but the specifications and requirements are quite similar to already available solutions like Vinted, eBay, or Depop. These platforms have established reputations, and the goal for the company was to bring all sellers in their industry together to trade in one place.
For the Minimum Viable Product (MVP), there was quite an extensive list of features and capabilities expected, including:
As this blog focuses primarily on backend technology, I will keep the discussion limited to backend stacks.
Based on project needs and our proficiency in Node.js (Typescript), we selected it for backend API development. The main question was whether to write the API from scratch or extend an existing solution.
Weighing the two options:
In the end, we decided to pick Medusa for the following reasons:
The rest of the tech stack was decided based on Medusa, as it integrates seamlessly with many existing adapters.
PostgreSQL is the primary supported database for Medusa. We initially tried CockroachDB but encountered issues with certain data types, so we opted for the recommended PostgreSQL, which we set up using Google Cloud SQL.
Medusa comes with built-in authentication, but we needed social authentication (at least Google). Fortunately, there is a Medusa plugin for this, which made it easy to set up. We just needed to configure Google credentials and environment variables.
medusa-plugin-marketplace
This being the third marketplace I’ve built with Medusa, I’ve come across things I wished were essentially plug-and-play to transform a fresh Medusa installation into a basic marketplace. So, I decided to consolidate these elements and publish them as a public plugin: medusa-plugin-marketplace
.
It includes the following features:
The plugin is still a work-in-progress, and more work is needed to make it customizable to user needs. Please give it a star to support the work.
Medusa supports both in-memory and Redis caching via plugins. For production use, Redis is recommended, so we opted for Redis.
We implemented the Redis event module for Medusa, which is essential for listening to certain events and triggering actions, such as:
We implemented Algolia search but found that the existing module wasn’t customizable enough for our business needs. Since our products are volatile and constantly deleted once out of stock, I wrote a custom Algolia search module for Medusa. This reduced the payload saved in the index. Although this approach comes at a cost with increased search traffic, it allowed us to get the MVP to market quickly. However, we are considering switching to Meilisearch in the future due to the costs associated with Algolia.
We opted for Google Cloud App Engine to deploy the backend because of its scalability and integration with other dependencies like the database and storage. Though documentation for deploying Medusa to App Engine is scarce, setting it up was straightforward with the right IAM configurations and a continuous deployment setup using Cloud Build.
For file storage, we used Google Cloud Storage and wrote a custom Medusa file module to access public and private buckets. There was an issue with Medusa’s hardcoded /uploads
folder (App Engine only allows writing to /tmp
), so we patched it to resolve the issue.
Notifications are a key part of the project. Our requirements included:
To meet these needs, we opted for a notification orchestration system. We chose Novu due to its open-source availability and affordable pricing (compared to Knock). For push notifications, we used Expo Notifications, but we encountered issues integrating Bird (formerly MessageBird) with Novu, so we wrote a custom module to handle authentication codes while Novu handles the rest.
Another requirement was enabling price negotiation between buyers and sellers. This involved actions like:
We stored offer histories and used custom carts to redirect buyers once offers were approved. Notifications were crucial here since offers expire within a set timeframe.
For messaging, we initially planned a simple email-like system, but the scope expanded to include:
We used the Medusa Sentry plugin for error reporting. More details can be found in the documentation.
The requirements for shipping included:
Although Medusa has a plugin for Webshipper, we opted for Shippo due to its free entry and great documentation. Since there wasn’t a good Shippo plugin for Medusa, we wrote a custom integration, allowing us to customize workflows like setting fixed shipping prices.
During the early stages, we needed a product approval flow where the marketplace could review products before they went live. Fortunately, Medusa offers these statuses out-of-the-box, so we just needed to implement filtering with Algolia and build a custom UI for super admins to review products.
This is just a surface level look at how the system was created and the reasoning behind certain decisions without going into detail of how to implement certain features, if you require more information regarding building out these systems or questions feel free to reach out via email.