Welcome to the Fleet Management Series
This is Part 1 of an 8-part tutorial series where we build a Fleet Management System from scratch โ the kind of system used by energy logistics and distribution companies to track hundreds of fuel trucks, manage drivers, and optimize delivery routes in real time.
By the end of this series, you'll understand how senior developers think about building enterprise applications. We won't just write code โ we'll make architectural decisions, explain why we chose each technology, and show you the mistakes that most tutorials never talk about.
What We're Building
Imagine you work at an energy distribution company. Every day, 200+ fuel trucks leave warehouses to deliver fuel to gas stations across the country. You need to:
- ๐บ๏ธ Track every truck in real time on a map
- ๐จโโ๏ธ Manage drivers โ schedules, certifications, performance
- ๐ฆ Track deliveries โ which truck carries what, where it's going
- โฝ Monitor fuel levels โ prevent theft, detect leaks
- ๐ Generate reports โ for compliance, billing, optimization
- ๐ Alert operators โ when something goes wrong
This is not a toy project. This is the kind of system that companies pay millions for.
What is System Architecture?
If you're new to software architecture, think of it like building a house.
You could start hammering nails immediately. But a professional builder first creates a blueprint: where the walls go, where the plumbing runs, how electricity flows. Architecture is the blueprint of your software.
Why Architecture Matters
Here's what happens when teams skip architecture:
Month 1: "Let's just build it in one big Next.js app!"
Month 3: "The API is getting slow... let's add some caching"
Month 6: "We can't deploy the admin panel without breaking the tracking page"
Month 9: "Everything is tangled together, we need to rewrite"
I've seen this happen at three different companies. The rewrite always costs 3-5x more than doing architecture properly from the start.
The Key Question: Monolith or Microservices?
Before we design anything, we need to answer this question. Let me explain both approaches simply:
Monolith = Everything in one application
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ One Big Application โ
โ โโโโโโโโ โโโโโโโโ โโโโโโโ โ
โ โTrack โ โAdmin โ โAPI โ โ
โ โ ing โ โPanel โ โ โ โ
โ โโโโโโโโ โโโโโโโโ โโโโโโโ โ
โ One Database โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Microservices = Multiple small applications, each doing one thing
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ
โ Tracking โ โ Admin โ โ Telemetryโ
โ Service โ โ Service โ โ Service โ
โ (Next.js)โ โ(Laravel) โ โ (NestJS) โ
โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ
โ โ โ
โโโโโโผโโโโโโ โโโโโโผโโโโโโ โโโโโโผโโโโโโ
โ MySQL โ โ MySQL โ โPostgreSQLโ
โโโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโ
Senior Decision: Which One Should We Choose?
Here's what separates junior from senior thinking:
Junior thinking: "Microservices are modern and cool, let's use them!"
Senior thinking: "What are our actual requirements? How big is our team? What's our deployment timeline?"
For our fleet management system, I chose a hybrid approach โ and here's why:
| Factor | Our Situation | Decision |
|---|---|---|
| Team size | 4-6 developers | Too small for full microservices |
| Domains | Very different (real-time tracking vs business admin) | Separate services make sense |
| Performance | Telemetry needs high throughput | Dedicated service needed |
| Time to market | 3-4 months for MVP | Can't build 10 microservices |
Our architecture: 3 services, not 30.
Our System Architecture
Here's the architecture we'll build throughout this series:
โโโโโโโโโโโโโโโโโโโโโโโ
โ Users/Operators โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Next.js Frontend โ
โ (Dashboard App) โ
โ - Fleet Map โ
โ - Reports โ
โ - Driver Mgmt โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ HTTPS
โโโโโโโโโโโโผโโโโโโโโโโโ
โ Nginx Reverse โ
โ Proxy โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโโโโผโโโโโโโโโ โโโโโโผโโโโโโโโโโ โโโโโโผโโโโโโโโโโโ
โ NestJS API โ โ Laravel API โ โ NestJS โ
โ (Main Backend) โ โ (Admin) โ โ (Telemetry) โ
โ โ โ โ โ โ
โ - Auth โ โ - Filament โ โ - GPS Ingest โ
โ - Fleet CRUD โ โ - Invoicing โ โ - Fuel Monitorโ
โ - Route Planning โ โ - Scheduling โ โ - Alerts โ
โโโโโโโโโโฌโโโโโโโโโโ โโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โโโโโโโโโโผโโโโโโโโโโ โโโโโโโผโโโโโโโโโ โโโโโโโโโผโโโโโโโโ
โ MySQL โ โ MySQL โ โ PostgreSQL โ
โ (Main Data) โ โ (Admin Data) โ โ (Telemetry) โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ
โโโโโโโโผโโโโโโโโ
โ Redis โ
โ (Cache + โ
โ Pub/Sub) โ
โโโโโโโโโโโโโโโโ
Why This Stack? (Tech Stack Decision Matrix)
Every technology choice should have a reason. Here's our decision matrix:
Frontend: Next.js (TypeScript)
| Considered | Pros | Cons | Decision |
|---|---|---|---|
| Next.js | SSR for SEO, great DX, React ecosystem | Heavier than SPA | โ Selected |
| Remix.js | Great data loading, web standards | Smaller ecosystem | Considered for future |
| Vue/Nuxt | Simple learning curve | Team expertise is React | โ Rejected |
Why Next.js? Our dashboard needs server-side rendering for initial load performance (operators open it first thing in the morning on slow office WiFi). The React ecosystem gives us map libraries, chart libraries, and real-time WebSocket support.
Main Backend: NestJS (TypeScript)
| Considered | Pros | Cons | Decision |
|---|---|---|---|
| NestJS | Structured, TypeScript, DI built-in | Learning curve | โ Selected |
| Express.js | Simple, flexible | No structure, becomes messy | โ Rejected |
| Fastify | Fast | Less ecosystem than NestJS | โ Rejected |
Why NestJS? Express.js is fine for small APIs, but for an enterprise application with 50+ endpoints, you need structure. NestJS gives us modules, dependency injection, and decorators โ patterns that keep code organized as the team grows.
Admin Service: Laravel (PHP)
| Considered | Pros | Cons | Decision |
|---|---|---|---|
| Laravel | Filament admin, Eloquent ORM, mature | Separate language | โ Selected |
| NestJS Admin | Same language as main API | No good admin panel lib | โ Rejected |
| Django | Good admin, Python | Team doesn't know Python | โ Rejected |
Why Laravel alongside NestJS? This might seem strange โ why use two backend languages? The answer is pragmatic: Laravel + Filament gives us a production-ready admin panel in days, not weeks. Building the same admin UI in React would take 3x longer. Senior developers choose the right tool for each job, not one tool for every job.
Databases: PostgreSQL + MySQL + Redis
| Database | Used For | Why |
|---|---|---|
| PostgreSQL | GPS telemetry, sensor data | PostGIS extensions for geospatial queries, excellent for time-series |
| MySQL | Users, drivers, invoices, schedules | Great for transactional business data, team familiarity |
| Redis | Caching, real-time pub/sub, sessions | Microsecond reads, perfect for "where is truck X right now?" |
Requirements Gathering: A Senior Skill
Most tutorials jump straight to npx create-next-app. But in real companies, you spend the first 1-2 weeks understanding what you're building.
The Questions I Ask Before Writing Any Code
- Who are the users? โ Dispatchers, fleet managers, drivers, accountants
- What are the critical paths? โ Real-time tracking must never go down
- What's the scale? โ 200 trucks, 50 concurrent operators, 1000+ GPS pings/minute
- What are the compliance requirements? โ Fuel delivery must have audit trails
- What's the deployment environment? โ VPS in a local data center, not AWS
User Stories We'll Implement
Here are the key user stories for our MVP:
## Operator Stories
- As an operator, I can see all trucks on a real-time map
- As an operator, I can click a truck to see its current status
- As an operator, I get alerts when a truck deviates from its route
## Admin Stories
- As an admin, I can manage driver profiles and schedules
- As an admin, I can generate delivery invoices
- As an admin, I can view fleet performance reports
## System Stories
- The system receives GPS data from 200+ trucks every 10 seconds
- The system stores telemetry data for 12 months
- The system sends SMS alerts for critical events
SDLC: How We'll Build This
We'll follow a simplified Agile approach:
Sprint Plan
| Sprint | Duration | Deliverable | Series Part |
|---|---|---|---|
| Sprint 1 | Week 1-2 | Architecture + Frontend shell | Part 1-2 |
| Sprint 2 | Week 3-4 | Main API + Admin panel | Part 3-4 |
| Sprint 3 | Week 5-6 | Database + Data layer | Part 5 |
| Sprint 4 | Week 7-8 | Code quality + Refactoring | Part 6 |
| Sprint 5 | Week 9-10 | Microservices split + Scaling | Part 7 |
| Sprint 6 | Week 11-12 | Security + CI/CD + Deploy | Part 8 |
Version Control Strategy
We'll use Git Flow with these branches:
main โ Production-ready code
โโโ develop โ Integration branch
โ โโโ feature/fleet-dashboard โ Part 2
โ โโโ feature/nestjs-api โ Part 3
โ โโโ feature/laravel-admin โ Part 4
โ โโโ feature/database-design โ Part 5
โโโ release/v1.0 โ Pre-production testing
Code Review Process:
- Every feature branch requires a Pull Request
- At least 1 reviewer must approve
- CI pipeline must pass (lint + test + build)
- No direct commits to
mainordevelop
Project Structure Preview
Here's how our monorepo will be organized:
fleet-management-system/
โโโ apps/
โ โโโ web/ # Next.js Frontend (Part 2)
โ โ โโโ src/
โ โ โ โโโ components/ # Reusable UI components
โ โ โ โโโ pages/ # Next.js pages
โ โ โ โโโ hooks/ # Custom React hooks
โ โ โ โโโ services/ # API client functions
โ โ โ โโโ types/ # TypeScript type definitions
โ โ โโโ package.json
โ โ
โ โโโ api/ # NestJS Main Backend (Part 3)
โ โ โโโ src/
โ โ โ โโโ modules/
โ โ โ โ โโโ auth/ # Authentication module
โ โ โ โ โโโ fleet/ # Fleet management module
โ โ โ โ โโโ driver/ # Driver management module
โ โ โ โ โโโ route/ # Route planning module
โ โ โ โโโ common/ # Shared utilities
โ โ โ โโโ main.ts
โ โ โโโ package.json
โ โ
โ โโโ admin/ # Laravel Admin Panel (Part 4)
โ โ โโโ app/
โ โ โ โโโ Filament/ # Filament resources
โ โ โ โโโ Models/ # Eloquent models
โ โ โ โโโ Services/ # Business logic
โ โ โ โโโ Events/ # Event listeners
โ โ โโโ composer.json
โ โ
โ โโโ telemetry/ # NestJS Telemetry Service (Part 7)
โ โโโ src/
โ โ โโโ modules/
โ โ โ โโโ gps/ # GPS data ingestion
โ โ โ โโโ fuel/ # Fuel monitoring
โ โ โ โโโ alert/ # Alert system
โ โ โโโ main.ts
โ โโโ package.json
โ
โโโ packages/
โ โโโ shared/ # Shared types and utilities
โ โโโ types/
โ โโโ constants/
โ
โโโ docker-compose.yml # Local development setup
โโโ .github/workflows/ # CI/CD pipelines (Part 8)
โโโ README.md
Common Mistakes to Avoid
From my 6+ years of building enterprise applications, here are mistakes I see teams make:
Mistake 1: Premature Microservices
Don't start with 15 microservices. Start with 2-3 services that have clear boundaries. You can always split later โ but merging microservices back together is painful.
Mistake 2: Choosing Tech for Your Resume
Don't use Kubernetes, Kafka, and GraphQL just because they look good on a resume. Choose technologies that solve your actual problems. Our fleet system uses simple Redis pub/sub instead of Kafka because we have 1000 messages/minute, not 1 million.
Mistake 3: No Architecture Decision Records (ADRs)
Do document why you chose each technology. Six months from now, when a new team member asks "why are we using two different backend frameworks?", you want a written answer โ not "I think Fari decided that, but he's on vacation."
Mistake 4: Skipping the Requirements Phase
Don't start coding on day one. Spend at least a few days understanding the business domain. The most expensive bugs are requirements bugs โ building the wrong thing perfectly.
What's Next
In Part 2, we'll build the Next.js frontend โ a real-time fleet tracking dashboard with a map view, vehicle status cards, and responsive layout. We'll cover:
- Setting up Next.js with TypeScript (strict mode)
- Component architecture decisions
- SSR vs CSR โ which pages need what
- Building the map integration
- State management patterns
This is Part 1 of the Fleet Management System series. Follow along as we build a production-grade enterprise application from scratch, covering every aspect of senior full-stack development.
