Architecture is the backbone of any successful project — but let’s be honest, it’s often the most ignored part too. Sometimes it’s because the engineering team is new to this, sometimes it’s lack of clarity from the product side, and other times it’s just us developers getting excited and diving in without a clear plan (we’ve all done it).
And while these reasons are valid, they don’t excuse skipping a proper architecture document — or at least a basic diagram — before building anything.
Let’s paint a picture:
Company A gets a new client and agrees to deliver a shiny new system in three months — without any technical consultation to check if that’s even doable. So, they call on the office superstar dev (you know the one) to either take it on solo (yikes!) or lead a small team.
The dev jumps in, follows the prototype or functional document, assigns tickets, reviews code, and the rest of the team breathes easy because “they’ve got this.” Everyone just sticks to their task, checks if the PR looks okay, merges it, and calls it a day. All smooth on the surface.
But here’s the problem: every project has an architecture, whether you write it down or not. The issue? In this case, the architecture lives inside the head of that one engineer. No shared doc, no diagram, just vibes.
So what happens when that superstar moves on? Maybe their contract ends, maybe they switch jobs. For a while, things still run fine. Then it starts getting harder to make changes. Product wants updates, and now the devs are stuck untangling code they didn’t design. Leadership starts asking questions. Another “super” dev joins, brings their own style, and the codebase becomes a patchwork of different ideas. Devs come and go, and maintaining the project becomes a nightmare.
All this could’ve been avoided with just one shared document at the start.
A project’s culture is set in the beginning. If the person kicking it off is in too much of a hurry to document the structure, that pressure usually trickles down.
But as engineers, we should get into the habit of documenting our architecture, even if it’s not perfect from day one. Trust me, future-you (or the next dev) will thank you.
So, about our e-commerce project...
We’re going to build it using microservices — mainly for the sake of learning.
In most cases, I’d recommend starting with a monolith and then splitting it up later once things get more complex. Microservices can get messy fast and there is usually a lot of technical debt to be paid in the long run.
We’ll pretend our product team gave us a functional spec and a Figma prototype. With that, here’s how we’ll break things down before designing our architecture:
Questions to answer before designing:
- What services do we need, and what should each do?
- What pieces of code will be shared?
- How will services find each other?
- How will services talk to each other?
- What does our infrastructure look like?
Once we’ve thought this through, we’ll draw up an architecture diagram and write a supporting doc in our next article.
🧱 Services and What They Do
We’re going all-in on Go for this one — every service will be written in Golang. Here's a rough list:
- Auth Service: Handles user creation, login, and role management (admin, vendor, customer).
- Notification Service: Sends in-app, email, or SMS messages.
- Order Service: Allows customers to place product orders from vendors.
- Product Service: Stores product details like name, color, description, etc.
- Payment Service: Handles order payments, subscriptions, and transactions.
- Review & Rating Service: Enables users to rate and review products and vendors.
- Search & Recommendation Service: Search and recommend products intelligently.
- Subscription & Traffic Service: Manages plans and vendor traffic quotas.
- Vendor Service: Lets vendors manage stores, inventory, orders, and deliveries.
Each of these services will have its own database — keeping things loosely coupled and scalable.
🔁 Shared Code
Some things show up across multiple services — we’ll put these in a shared library:
- API Signatures/Types
- Message Broker Code
- Database Connections
- Env Configs
- Events
- Logging
- Tracing (OpenTelemetry)
- Protobuf Definitions
- Utilities (pagination, request parsing, etc.)
⚠️ Heads-up: Too much shared code = tight coupling. We'll keep it modular.
🧭 How Services Find Each Other (Service Discovery)
To start, we’ll hardcode service routes into the API Gateway — works fine during early dev.
Later, when we move to a multi-node Kubernetes setup, we’ll explore tools like Istio for smarter service discovery.
📡 How Services Communicate
Two main ways:
1. Synchronous (Blocking) — Using gRPC
Use this when we need an instant response — e.g. during user registration:
- Auth Service
- Vendor Profile Service
- Subscription Service
- Payment Service
2. Asynchronous (Non-blocking) — Using Message Brokers
For example: A "payment successful" webhook triggers an event. Services like Subscription can pick it up and react independently.
This helps decouple services and improve system resilience.
⚙️ Infrastructure Setup
To start:
- All services run on the same server
- Each service exposed via different ports
- API Gateway in front
- Dockerize all services and third-party tools like prometheus, postgres, etc.
Later on we'll:
- Move to Kubernetes (multi-node)
- Try AWS deployment
- Explore GitOps tools like ArgoCD
📊 Monitoring and Observability
Microservices = more moving parts. So we’ll need strong observability:
- Logging: Consistent, searchable logs
- Tracing: End-to-end request tracking with OpenTelemetry
- Metrics: Expose metrics with Prometheus; visualize with Grafana
🧩 Wrapping Up
This was just an intro to how we’ll approach architecture for our e-commerce project.
We’ll dive deeper into each section later and share code, diagrams, and repos along the way.
✅ What’s Next
- Sketch the architecture diagram
- Define all service APIs
- Set up the dev environment + repos
- Start building — first stop: Auth Service
Top comments (0)