Different Types of Architectures in Web Products

As web products evolve, selecting the right architecture becomes critical to ensure scalability, maintainability, and efficiency. In this article, I’ll break down some of the common web architectures, provide examples where relevant, and explain tricky concepts in simpler terms.
1. Monolithic Architecture
What It Is
A monolithic architecture is a single, unified application where all components — UI, business logic, and database operations — are tightly integrated. It’s like having a single piece of software handling everything in one big package.
Code Example
Here’s an example of a Node.js Express app written in a monolithic way:
const express = require('express');
const app = express();
app.get('/users', (req, res) => {
// Business logic and database handling here
const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
res.json(users);
});
app.post('/users', (req, res) => {
// Directly handle input and save to database
res.status(201).json({ message: 'User created' });
});
app.listen(3000, () => console.log('Server running on port 3000'))
Everything is centralized in one application. While simple to set up, it can become unwieldy as the application grows.
Pros:
- Simple to develop and deploy.
- Easier to debug in the early stages.
Cons (or the “tricky parts”):
- Hard to scale — adding features means modifying the whole app.
- If one part fails, the whole system can go down.
2. Microservices Architecture
What It Is
This approach breaks the application into small, independent services. Each service is responsible for a specific functionality, like user management or payment processing. It’s like a team of specialists, each doing one job well.
Code Example
Imagine a user service and an order service communicating with each other:
User Service (user-service.js):
const express = require('express');
const app = express();
app.get('/users', (req, res) => {
const users = [{ id: 1, name: 'Alice' }];
res.json(users);
});
app.listen(3001, () => console.log('User service running on port 3001'));
Order Service (order-service.js):
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/orders', async (req, res) => {
const users = await axios.get('http://localhost:3001/users');
res.json({ orders: [{ id: 101, user: users.data[0] }] });
});
app.listen(3002, () => console.log('Order service running on port 3002'));
Each service runs independently and communicates via APIs.
Pros:
- Scalability: You can scale individual services as needed.
- Resilience: If one service fails, the others can still function.
Cons:
- Complex to set up (requires orchestration tools like Kubernetes).
- Testing and debugging can be tricky since components interact over the network.
3. Serverless Architecture
What It Is
In serverless architecture, developers focus solely on writing code, while the cloud provider handles the infrastructure. It’s like going to a restaurant where you only need to decide what to eat (code) while the chef (cloud) does the cooking (manages servers).
Code Example
Here’s a basic AWS Lambda function using JavaScript:
exports.handler = async (event) => {
const name = event.queryStringParameters.name || 'Guest';
return {
statusCode: 200,
body: JSON.stringify({ message: `Hello, ${name}!` }),
};
};
You deploy this function, and AWS takes care of running it when triggered by an event.
Pros:
- Cost-effective: You only pay when your function runs.
- No server management.
Cons:
- Vendor lock-in: You’re tied to the cloud provider’s ecosystem.
- Cold start latency: Functions may take longer to start if they’ve been idle.
4. Single-Page Application (SPA) Architecture
What It Is
An SPA loads a single HTML page and dynamically updates content without reloading the page. It’s like an app that gets all its tools upfront and then works independently without going back to the toolbox.
Code Example
Here’s a React SPA:
App.js:
import React, { useState, useEffect } from 'react';
const App = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('/api/users')
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
return (
<div>
<h1>User List</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
export default App;
The server only serves the /api/users
endpoint, while the SPA handles rendering on the client.
Pros:
- Fast user experience (no full-page reloads).
- Great for interactive applications.
Cons:
- Poor SEO (can be mitigated with server-side rendering).
- Initial load can be heavy due to JavaScript bundling.
5. Progressive Web Application (PWA)
What It Is
PWAs combine the best of web and mobile apps. They work offline, load quickly, and can be installed on your device. It’s like a web app with superpowers!
Code Example
Here’s a Service Worker for offline caching in a PWA:
service-worker.js:
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll(['/index.html', '/styles.css', '/app.js']);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
Pros:
- Offline capability.
- Feels like a native app.
Cons:
- Complex to set up compared to traditional web apps.
- Limited access to some native device features.
6. Event-Driven Architecture
What It Is
In this architecture, components communicate by producing and consuming events. Think of it as a “publish-subscribe” system, like a news service where updates are sent to subscribers.
Code Example
Using Node.js with an event emitter:
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
// Subscriber
eventEmitter.on('userCreated', (user) => {
console.log(`Welcome email sent to ${user.name}`);
});
// Publisher
eventEmitter.emit('userCreated', { name: 'Alice', email: 'alice@example.com' });
Pros:
- Decoupled services: Components don’t need to know about each other.
- Great for real-time applications.
Cons:
- Debugging can be challenging due to asynchronous behavior.
- Requires reliable event processing infrastructure.
Final Thoughts
Each architecture has its strengths and weaknesses. Choosing the right one depends on your product’s size, goals, and team expertise. Start simple, and as your product grows, consider whether your architecture needs to evolve to handle new challenges.