Home
Blog
Community

Beginner Guide to a Node.js Ecommerce: Understanding Medusa's Server

Jun 30, 2022 by

undefined avatar

Hung Vu

undefined avatar

Hung Vu

Discover the power of Medusa, the leading open source Node.js ecommerce infrastructure, in this guide that takes a deep dive into Medusa's architecture.
Beginner’s Guide to a Node.js Ecommerce Platform: Understanding the Medusa Server
Notice Medusa is under active development, so the content of this post may be outdated. Please check out our documentation instead.
Medusa is the leading open source Node.js ecommerce platform for JavaScript developers. It provides similar core functionality as Shopify out-of-the-box, while its open abstraction-based and headless architecture makes customizations and maintenance much easier to handle for developers as businesses’ needs evolve.
Most of the heavy lifting job has been done by Medusa so that you can achieve a production-ready store in a short amount of time. Medusa’s abstract architecture also allows developers to extend and customize the platform to fit their use case hassle-free.
This article will take you through Medusa’s architecture and give you a general overview of the Medusa server to better understand how it works.

Medusa Architecture Overview

Image modal
Three main components of a Medusa project
Medusa’s complete architecture consists of three main components: Headless Node.js Ecommerce Server, Admin Dashboard, and Storefront. The modular and headless architecture makes all three components completely separated and deployable to different environments without any restriction.
To understand more what each component is:
  1. Medusa Server (Headless)
    • This is the core component and is the brain of your online store. It is a Node.js Ecommerce Server. Being a headless server, it is accessed via REST APIs. Both the storefront and admin dashboard are presentation layers to interact with the server.
    • Everything you configure in the admin dashboard or actions performed by consumers on the storefront are handled underneath by the Medusa server.
  2. Admin Dashboard
    • Only authorized personnel can access the admin dashboard. This is where you manage your online store’s data and settings such as adding products, setting price/currencies, and managing orders.
    • Medusa provides an intuitive admin built with Gatsby, but you can also create your own from scratch using the REST APIs.
  3. Storefront
    • A storefront is where consumers arrive, search for products and buy them. An example of a storefront is the Amazon website. You can either have one cross-platform storefront (e.g., web application), or multiple storefronts (e.g., web, iOS, and Android native applications).
    • Medusa provides two starter storefronts, one built using Next.js and one using Gatsby. You can also build your own storefront by interacting with the REST APIs.
This article focuses only on the Medusa server, as it is the core of your Node.js ecommerce platform.

Development Environment

Medusa relies mainly on Node.js to be installed on your system. You need version 14 or higher.
Medusa also uses other technologies and tools such as PostgreSQL and Redis.
This article covers how and when these components are used in your Medusa server. You can follow along this documentation to learn how to install each of the environment requirements.

How to install the Medusa server?

To install the Medusa server, you need to use the Medusa CLI tool. You can install the Medusa CLI tool with the following command:
npm install -g @medusajs/medusa-cli
Then, install a Medusa server with the following command
medusa new my-medusa-store --seed
Your server now resides in the
Copy to clipboard
my-medusa-store
folder. The
Copy to clipboard
--seed
option creates an SQLite database in the root of the project. The SQLite database holds dummy data for your server such as sample products, regions, and more. Seeded data is only for testing purposes in a development environment.
As using the SQLite database can present a lot of limitations in development and especially in production, it is recommended to install and set up a PostgreSQL database instead.

What is
Copy to clipboard
my-medusa-store
made of?

If you have worked with NestJS or Angular before, the folder structure might seem familiar. Navigate to
Copy to clipboard
my-medusa-store
, and you can see the content below.
Image modal
Inside my-medusa-store folder
For starters, the four main directories and files you want to focus on are
Copy to clipboard
data
,
Copy to clipboard
dist
,
Copy to clipboard
src
, and
Copy to clipboard
medusa-config.js
.
  1. Copy to clipboard
    data
    directory contains fake data to populate your demo store either using the
    Copy to clipboard
    --seed
    option or using the command
    Copy to clipboard
    npm run seed
    .
  2. Copy to clipboard
    medusa-config.js
    file is where you define project configuration, such as database information, service API keys, plugins, and more.
  3. Copy to clipboard
    src
    folder holds the implementation of your custom files, from custom endpoints (in
    Copy to clipboard
    api
    ) to global services (in
    Copy to clipboard
    services
    ) and event listeners (in
    Copy to clipboard
    subscribers
    ). These three child folders are going to be discussed in the next few sections.
  4. Copy to clipboard
    dist
    directory only appears after you run
    Copy to clipboard
    npm run build
    or
    Copy to clipboard
    medusa develop
    . It holds compiled files that are originally in the
    Copy to clipboard
    src
    directory. The compiled files will be used when you run the server.
For product image uploads you need to install and integrate file service plugins such as MinIO, Amazon S3, or DigitalOcean Spaces.

What is in the medusa-config.js file?

By default, the server contains the following variables.

ADMIN_CORS and STORE_CORS

The components are decoupled in Medusa. So, the Node.js ecommerce headless server, admin dashboard, and storefront can have different origins (e.g., different domains, or different ports on the same domain). This causes Avoid Cross-Origin Resource Sharing (CORS) and blocks communication between components.
The usage of CORS variables is a way to solve this issue. By default, the headless server runs on port
Copy to clipboard
9000
, the admin dashboard runs on port
Copy to clipboard
7000
or
Copy to clipboard
7001
, and the storefront is available at port
Copy to clipboard
8000
. If you decide to change the origins of the front ends or deploy components to different environments, then the CORS values must be adjusted accordingly.
# .env
# CORS when consuming Medusa from admin
ADMIN_CORS=http://localhost:7000
# CORS to avoid issues when consuming Medusa from a client
STORE_CORS=http://localhost:8000

DATABASE_URL

This is a connection string to the PostgreSQL instance.
PostgreSQL is a mature open source relational database that has been adopted by developers around the world. With its performance, reliability, and strict data integrity, PostgreSQL can support your online store even on a global scale.
For connection string construction, please refer to PostgreSQL official documentation.
# .env
# Sample of typical PostgreSQL connection string format
# postgres://<DB_USER>:<PASSWORD>@<HOST>:<PORT_NUMBER>/<DB_NAME>
DATABASE_URL=postgres://adminuser:password123@localhost:5432/my-medusa-database

REDIS_URL

This is a connection string to the Redis instance.
Redis is a high-performant open source in-memory data structure. In Medusa, it is used as an event queue, so all events-related features need Redis to be properly configured. More about how Medusa uses Redis is explained later in this guide.
For connection string, please refer to this guide.
# .env
# Sample of typical Redis connection string format
# redis://<REDIS_USER>:<PASSWORD>@<HOST>:<PORT_NUMBER>/<INSTANCE_NAME>
REDIS_URL=redis://superuser:redispassword@localhost:6379/my-redis-instance

Plugins

In many ecommerce solutions, extending the functionalities often requires a dedicated team and server resources. However, Medusa solves this by letting you incorporate new features to the core server process via plugins; thereby eliminating additional resource requirements.
Since Medusa is a Node.js ecommerce platform, a plugin is basically an NPM package. After installation, put the name of your plugin (package) in the
Copy to clipboard
plugins
variable and you are good to go. From here on out, the plugins can use all other Medusa services and even access the database.
const plugins = [
`plugin-without-options`,
{
resolve: `plugin-with-options`,
options: {
api_key: YOUR_PLUGIN_API_KEY,
...
},
},
];

How to run the Medusa server?

Use the following command in the root of the Medusa server directory to run the server:
medusa develop
The server will run on
Copy to clipboard
localhost:9000
. You can check the API reference for a list of endpoints you can use to interact with the server.

What is a custom endpoint in Medusa?

Let’s say you want to allow a business partner to access your inventory, what is the way to do so? Certainly, a protected API is the answer for you.
In the Medusa server, you can implement custom endpoints in the
Copy to clipboard
/src/api
folder. As Express is used internally, in a sense, the Medusa instance can act as a general public Express server. There is no limit to the endpoints. Your endpoints can be organized into one, or multiple files.
By conventions, endpoints for admin are prefixed with
Copy to clipboard
admin
, while endpoints for storefront are prefixed with
Copy to clipboard
store
.
For example:
/**
* /src/api/index.js
*/
import { Router } from "express"
export default () => {
const router = Router()
router.get("/admin/hello", (req, res) => {
res.json({
message: "Welcome to Your Store!",
})
})
return router
}
Implementation of APIs requires a certain degree of Express knowledge and is not discussed in this article. To dive deeper into endpoints in Medusa, check out the documentation on how to create endpoints.

What is a Service in Medusa?

Now that you know the Medusa server can create custom endpoints, let's revisit the B2B example:
You want to have a business partner accessing your inventory.
As stated, a protected API is required so only your partner can access the private inventory, and you know where the API is implemented, but where does the "private inventory access" feature reside?
Following the SOLID principle where an S represents single responsibility, files in
Copy to clipboard
/src/api
are controllers responsible for managing HTTP requests/responses and deciding what portion of the code should be called upon.
On the other hand, private inventory access is considered a service. Services in Medusa reside in
Copy to clipboard
/src/services
. They represent one specific entity and functionalities related to it.
An example of a service:
/**
* /src/services/privateInventoryAccess.js
*/
import { BaseService } from "medusa-interfaces"
class PrivateInventoryAccessService extends BaseService {
getUnreleasedProducts() {
...
}
}
export default PrivateInventoryAccessService
Services can be accessed anywhere on your Medusa server. For example, to use
Copy to clipboard
PrivateInventoryAccessService
in an endpoint:
/**
* /src/api/index.js
*/
// File name of service is "privateInventoryAccess.js", so its registration name
// is a camel-cased version: "privateInventoryAccessService"
// The service is accessible via req.scope.resolve(serviceRegistrationName)
const privateInventoryAccessService = req.scope.resolve("privateInventoryAccessService")
res.json({
unreleasedProducts: privateInventoryAccessService.getUnreleasedProducts(),
})
For a complete tutorial on service creation, you can start with official Medusa documentation.

What is a Subscriber in Medusa?

Medusa handles some specific but fundamental actions of a Node.js ecommerce platform such as order placement or user password reset. When an action happens, a respective event is emitted (for example, order placement emits an
Copy to clipboard
order.placed
event).
A subscriber is responsible for listening to these events and handling them. Internally, events rely on the Redis event queue. Events are pushed to this queue, then Redis will emit these events to the subscribers that are listening to them.
Without Redis being installed and configured, events are not emitted and subscribers will not work. You can download Redis at their official website.
You can achieve highly customizable workflows using subscribers. Many plugins such as SendGrid or Mailchimp use subscribers internally, and you can use them as a plug-and-play workflow extension.
Customized subscribers reside in
Copy to clipboard
/src/subscribers
. Here’s an example of a subscriber:
/**
* /src/subscribers/orderPlacementLogger.js
*/
class OrderPlacementLoggerSubscriber {
constructor({ eventBusService }) {
eventBusService.subscribe("order.placed", this.writeLog);
}
writeLog = async (data) => {
console.log(...)
};
}
export default OrderPlacementLoggerSubscriber;
For a complete tutorial on subscribers and how they work check out Medusa’s documentation.

Next Steps

This article should help you have a grasp of the Medusa server fundamentals. However, there’s still much more that you can do with Medusa.
Here are some additional resources to check out:
Don't forget to join Medusa's Discord as the team is there to help if you have any questions.

Share this post

Try Medusa

Spin up your environment in a few minutes.