Microservices vs. Micro Frontends: What's the Difference?

Pavan Belagatti - Jul 25 '23 - - Dev Community

In the ever-evolving landscape of software development, two groundbreaking architectural styles, microservices, and micro frontends, have emerged as transformative paradigms. These methodologies have been redefining the way modern applications are built and deployed. Embracing the principles of modularity, scalability, and flexibility, both microservices and micro frontends have become favored choices among development teams worldwide.

Whether you are a seasoned developer or just beginning your journey into the world of software architecture, this guide aims to equip you with a comprehensive understanding of microservices and micro frontends, and how they can elevate your application development to new heights.

What are Microservices?

Microservices is an architectural style where a monolithic application is divided into several small, loosely coupled, and independent services. All these microservices work together to form a larger system. Each service in a microservices architecture represents a specific business capability and operates as a separate unit with its own database and logic.

Microservices Tutorial

Step 1: Setting Up the Project

Create a new folder for your project and initialize a new Node.js project. Open a terminal and run the following commands:

mkdir microservices-tutorial
Enter fullscreen mode Exit fullscreen mode
cd microservices-tutorial
Enter fullscreen mode Exit fullscreen mode
npm init -y
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Dependencies

We will use Express.js and Axios for this tutorial. Install them using npm:

npm install express axios
Enter fullscreen mode Exit fullscreen mode

Step 3: Create Microservices

For this tutorial, we'll create two microservices: a "users" service and an "orders" service. The "users" service will handle user-related operations, while the "orders" service will handle order-related operations.

Create two folders, "users" and "orders," inside the main project folder. Inside each folder, create an index.js file.

Step 4: Implement Microservices

Let's start by implementing the "users" service. Open the users/index.js file and add the following code:

const express = require('express');
const app = express();
const port = 3000;

app.get('/users', (req, res) => {
  const users = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Smith' },
    { id: 3, name: 'Bob Johnson' },
  ];
  res.json(users);
});

app.listen(port, () => {
  console.log('Users service is running on port ' + port);
});
Enter fullscreen mode Exit fullscreen mode

Now, let's implement the "orders" service. Open the orders/index.js file and add the following code:

const express = require('express');
const app = express();
const port = 4000;

app.get('/orders', (req, res) => {
  const orders = [
    { id: 1, product: 'Product A' },
    { id: 2, product: 'Product B' },
    { id: 3, product: 'Product C' },
  ];
  res.json(orders);
});

app.listen(port, () => {
  console.log('Orders service is running on port ' + port);
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Communicating Between Microservices

In this step, we will use Axios to make HTTP requests from one microservice to another. We'll modify the "users" service to fetch orders from the "orders" service.

Open the users/index.js file again and add the following code:

const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;
const ordersServiceURL = 'http://localhost:4000';

app.get('/users', async (req, res) => {
  try {
    const response = await axios.get(`${ordersServiceURL}/orders`);
    const orders = response.data;

    const users = [
      { id: 1, name: 'John Doe', orders: orders.slice(0, 2) },
      { id: 2, name: 'Jane Smith', orders: orders.slice(1, 3) },
      { id: 3, name: 'Bob Johnson', orders: orders.slice(0, 1) },
    ];

    res.json(users);
  } catch (error) {
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(port, () => {
  console.log('Users service is running on port ' + port);
});
Enter fullscreen mode Exit fullscreen mode

Step 6: Run the Microservices

To run the microservices, open two separate terminals, navigate to the project folder, and run the following commands:

For the "users" service:

cd users
Enter fullscreen mode Exit fullscreen mode
node index.js
Enter fullscreen mode Exit fullscreen mode

For the "orders" service:

cd orders
Enter fullscreen mode Exit fullscreen mode
node index.js
Enter fullscreen mode Exit fullscreen mode

Step 7: Test the Microservices

Open your web browser or use a tool like Postman to test the microservices.

To test the "users" service, navigate to http://localhost:3000/users. It should return a list of users along with their associated orders.

To test the "orders" service, navigate to http://localhost:4000/orders. It should return a list of orders.

Congratulations! You've successfully created a basic microservices architecture using Node.js, Express.js, and Axios, where two microservices communicate with each other to fulfill a user request.

What are Micro Frontends?

Micro Frontends is a web development architectural pattern that extends the principles of microservices to the frontend of web applications. It involves breaking down the user interface of a web application into smaller, loosely coupled, and independently deployable frontend modules. Each module represents a distinct feature or functionality of the application and can be developed, tested, and deployed independently.

Micro Frontends Tutorial

Let's see how micro frontends work practically with a simple tutorial.

In this example, we will use Express.js to create a server that serves the individual microfrontends as static files. We also use the http-proxy-middleware library to proxy requests to the appropriate microfrontend based on the URL path. Let's get going!!!

Step 1: Set Up the Microfrontend Architecture

Create a new directory for your project and initialize a new Node.js project:

mkdir microfrontend-example
Enter fullscreen mode Exit fullscreen mode
cd microfrontend-example

Enter fullscreen mode Exit fullscreen mode
npm init -y

Enter fullscreen mode Exit fullscreen mode

Step 2: Install Dependencies

Install the required dependencies for your microfrontend project:

npm install express
Enter fullscreen mode Exit fullscreen mode
npm install express-http-proxy
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Microfrontends

In this tutorial, we'll create two microfrontends: frontend1 and frontend2.

Inside the project directory, create a frontend1 directory with an index.html file:

<!-- frontend1/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Frontend 1</title>
</head>
<body>
  <h1>Frontend 1</h1>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

Similarly, create a frontend2 directory with an index.html file:

<!-- frontend2/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Frontend 2</title>
</head>
<body>
  <h1>Frontend 2</h1>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Microfrontend Server

Create a new file named server.js in the project root directory:

// server.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

// Serve frontend1
app.use('/frontend1', express.static('frontend1'));

// Serve frontend2
app.use('/frontend2', express.static('frontend2'));

// Proxy requests to the appropriate microfrontend
app.use('/microfrontend1', createProxyMiddleware({ target: 'http://localhost:3000/frontend1', changeOrigin: true }));
app.use('/microfrontend2', createProxyMiddleware({ target: 'http://localhost:3000/frontend2', changeOrigin: true }));

// Start the server
app.listen(3000, () => {
  console.log('Microfrontend server started on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Start the Microfrontend Server
In the terminal, run the following command to start the microfrontend server:

node server.js
Enter fullscreen mode Exit fullscreen mode

Step 6: Access the Microfrontends
Open your browser and visit http://localhost:3000/microfrontend1 to see frontend1, and http://localhost:3000/microfrontend2 to see frontend2.

Congratulations! You have successfully created a simple microfrontend setup using Node.js.

When to use Micro Frontends?

Micro frontends and microservices are architectural patterns used to build scalable and modular applications, but they address different concerns and are suitable for different scenarios.

  • Micro frontends are used when you have a complex web application that requires multiple teams to work independently on different parts of the user interface. By breaking the frontend into smaller, self-contained modules, each team can develop and deploy their features separately, enabling faster development cycles and easier maintenance. This approach is particularly useful in large organizations with multiple frontend teams or when dealing with legacy codebases that need to be incrementally modernized.

  • On the other hand, microservices are employed when designing the backend architecture of an application. With microservices, the backend is split into small, autonomous services, each responsible for a specific business capability. This promotes better scalability, fault isolation, and independent deployment of services. Microservices are a better fit for applications with complex business logic, requiring flexibility in technology choices, and the ability to scale different components independently.

Below is the chart that shows the differences between microservices and micro frontends.

differences between microservices and micro frontends

In summary, use micro frontends when dealing with frontend complexity and multiple development teams, and opt for microservices when you need to create a scalable and modular backend architecture. Both patterns can complement each other in building a comprehensive, decoupled, and flexible system.

Note: I have taken the help of OpenAI in some parts of this tutorial.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .