Overview
The Tracking Service records the complete lifecycle of shipments from warehouse departure to final delivery. It provides real-time tracking capabilities and stores diverse event data using MongoDB’s flexible schema.
Port: 8091 | Database: MongoDB (trackingdb) | Eureka Name: msvc-tracking
Responsibilities
Shipment Creation Initialize tracking records when Order Service confirms orders
Event Recording Track shipment events (departed, in transit, customs, delivered)
Tracking Number Generation Generate unique UUID-based tracking numbers for customers
Real-Time Updates Provide current shipment status and location information
Why MongoDB (NoSQL)?
MongoDB was specifically chosen for the Tracking Service due to its unique requirements:
Different shipping events require different data:
Departure : Warehouse location, carrier info
In Transit : GPS coordinates, current location
Customs : Customs declaration number, inspection notes
Delivery : Delivery photo, recipient signature, timestamp
Exception : Weather delay info, traffic data, incident reports
With MongoDB, you can store heterogeneous events without ALTER TABLE migrations. Each event can have its own unique fields.
Events are stored as an embedded array, allowing unlimited event history without JOIN operations: {
_id : ObjectId ( "..." ),
orderId : 789 ,
trackingNumber : "TRK-f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
events : [
{
status: "Departed" ,
timestamp: ISODate ( "2026-03-08T10:00:00Z" ),
location: "Warehouse A" ,
details: "Package picked up"
},
{
status: "In Transit" ,
timestamp: ISODate ( "2026-03-08T14:30:00Z" ),
location: "Distribution Center" ,
gpsCoordinates: { lat: 40.7128 , lng: - 74.0060 },
vehicleId: "TRUCK-456"
},
{
status: "Delivered" ,
timestamp: ISODate ( "2026-03-09T11:15:00Z" ),
location: "Customer Address" ,
deliveryPhoto: "https://cdn.example.com/proof-123.jpg" ,
recipientSignature: "base64encodedimage..." ,
recipientName: "John Doe"
}
]
}
Tracking events are write-heavy (constant status updates). MongoDB excels at:
High-frequency writes (event appending)
No complex relationships or JOINs required
Natural fit for event sourcing patterns
Horizontal scaling for high-volume tracking data
The entire shipment with all its events is a single document, eliminating:
Complex JOIN queries
N+1 query problems
Foreign key constraints
Normalization overhead
Not for Transactions : MongoDB (in this setup) is used for event logging, not transactional data. Critical order state lives in Order Service (PostgreSQL).
Domain Model
Shipment Document (MongoDB Collection)
Based on the technical specification:
// MongoDB document structure
{
_id : ObjectId ( "65f9b2c4d1e2f3a4b5c6d7e8" ),
orderId : 789 , // Reference to Order Service
trackingNumber : "TRK-UUID" , // Customer-facing tracking code
carrier : "DHL" , // Shipping carrier
estimatedDelivery : ISODate ( "2026-03-10T00:00:00Z" ),
currentStatus : "In Transit" ,
events : [
{
status: "Warehouse Departure" ,
timestamp: ISODate ( "2026-03-08T10:00:00Z" ),
location: "Distribution Center - East" ,
details: "Package sorted and loaded"
},
{
status: "In Transit" ,
timestamp: ISODate ( "2026-03-08T14:30:00Z" ),
location: "Highway 95 North" ,
gpsCoordinates: {
latitude: 40.7128 ,
longitude: - 74.0060
},
vehicleId: "TRUCK-456" ,
driverName: "Mike Johnson"
},
{
status: "Customs Clearance" ,
timestamp: ISODate ( "2026-03-08T18:00:00Z" ),
location: "International Border - Port 12" ,
customsDeclaration: "DEC-2026-12345" ,
inspectionNotes: "Standard inspection completed"
},
{
status: "Out for Delivery" ,
timestamp: ISODate ( "2026-03-09T08:00:00Z" ),
location: "Local Distribution Hub" ,
details: "Assigned to delivery route 42"
},
{
status: "Delivered" ,
timestamp: ISODate ( "2026-03-09T11:15:00Z" ),
location: "123 Main St, Customer Address" ,
deliveryProof: {
recipientName: "John Doe" ,
signature: "data:image/png;base64,..." ,
photo: "https://cdn.tracking.com/proof/789-delivered.jpg"
},
weatherCondition: "Sunny, 72°F"
}
]
}
Java Domain Model
package com.microservice.tracking.domain.model;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* Shipment aggregate root.
* Manages tracking events and shipment lifecycle.
*/
public class Shipment {
private String id ; // MongoDB ObjectId
private Long orderId ;
private String trackingNumber ;
private String carrier ;
private LocalDateTime estimatedDelivery ;
private String currentStatus ;
private List < TrackingEvent > events ;
public Shipment ( Long orderId , String carrier ,
LocalDateTime estimatedDelivery ) {
this . orderId = orderId;
this . trackingNumber = generateTrackingNumber ();
this . carrier = carrier;
this . estimatedDelivery = estimatedDelivery;
this . currentStatus = "Created" ;
this . events = new ArrayList <>();
// Add initial event
addEvent ( new TrackingEvent (
"Created" ,
LocalDateTime . now (),
"System" ,
"Shipment record created"
));
}
/**
* Add a new tracking event.
* Updates current status to match latest event.
*/
public void addEvent ( TrackingEvent event ) {
this . events . add (event);
this . currentStatus = event . getStatus ();
}
/**
* Generate unique tracking number using UUID.
*/
private String generateTrackingNumber () {
return "TRK-" + UUID . randomUUID (). toString ();
}
public boolean isDelivered () {
return "Delivered" . equalsIgnoreCase (currentStatus);
}
// Getters...
}
Tracking Event Value Object
package com.microservice.tracking.domain.model;
import java.time.LocalDateTime;
import java.util.Map;
/**
* Represents a single tracking event.
* Flexible structure allows different events to carry different data.
*/
public class TrackingEvent {
private String status ;
private LocalDateTime timestamp ;
private String location ;
private String details ;
private Map < String , Object > metadata ; // Flexible additional data
public TrackingEvent ( String status , LocalDateTime timestamp ,
String location , String details ) {
this . status = status;
this . timestamp = timestamp;
this . location = location;
this . details = details;
this . metadata = new HashMap <>();
}
/**
* Add custom metadata (GPS, photos, signatures, etc.)
*/
public void addMetadata ( String key , Object value ) {
this . metadata . put (key, value);
}
// Getters...
}
Expected API Endpoints
Base URL: http://localhost:8091/api/v1/tracking
POST /shipment - Create Shipment
Called by Order Service to initialize tracking for a new order. Request Body: {
"orderId" : 789 ,
"carrier" : "DHL" ,
"estimatedDelivery" : "2026-03-10" ,
"customerName" : "John Doe" ,
"deliveryAddress" : "123 Main St, City, State"
}
Response (201 Created): {
"trackingNumber" : "TRK-f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"orderId" : 789 ,
"carrier" : "DHL" ,
"currentStatus" : "Created" ,
"estimatedDelivery" : "2026-03-10T00:00:00"
}
GET /{trackingNumber} - Get Shipment Status
Public endpoint for customers to track their shipments. Response: {
"trackingNumber" : "TRK-f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"orderId" : 789 ,
"carrier" : "DHL" ,
"currentStatus" : "In Transit" ,
"estimatedDelivery" : "2026-03-10T00:00:00" ,
"events" : [
{
"status" : "Warehouse Departure" ,
"timestamp" : "2026-03-08T10:00:00" ,
"location" : "Distribution Center - East" ,
"details" : "Package sorted and loaded"
},
{
"status" : "In Transit" ,
"timestamp" : "2026-03-08T14:30:00" ,
"location" : "Highway 95 North" ,
"gpsCoordinates" : {
"latitude" : 40.7128 ,
"longitude" : -74.0060
}
}
]
}
POST /{trackingNumber}/event - Add Tracking Event
Called by shipping systems or warehouse staff to update shipment status. Request Body: {
"status" : "Delivered" ,
"location" : "Customer Address" ,
"details" : "Package delivered to recipient" ,
"metadata" : {
"recipientName" : "John Doe" ,
"signature" : "data:image/png;base64,..." ,
"photo" : "https://cdn.example.com/delivery-proof.jpg"
}
}
Response: 204 No Content
GET /order/{orderId} - Get Tracking by Order ID
Internal endpoint for Order Service to retrieve tracking info. Response: {
"trackingNumber" : "TRK-f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"currentStatus" : "In Transit" ,
"lastUpdate" : "2026-03-08T14:30:00"
}
Database Configuration
server :
port : 8091
mongodb :
user : root
password : password
database : trackingdb
spring :
application :
name : msvc-tracking
data :
mongodb :
uri : mongodb://${mongodb.user}:${mongodb.password}@localhost:27017/${mongodb.database}
config :
import : "optional:configserver:http://localhost:8888"
eureka :
instance :
hostname : eureka-server
client :
service-url :
defaultZone : http://${eureka.instance.hostname}:8761/eureka/
The service connects to MongoDB running in Docker container tracking_db on port 27017.
MongoDB Repository Pattern
Repository Interface
package com.microservice.tracking.infrastructure.persistence;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.microservice.tracking.domain.model.Shipment;
import java.util.Optional;
/**
* Spring Data MongoDB repository.
*/
public interface ShipmentRepository extends MongoRepository < Shipment , String > {
Optional < Shipment > findByTrackingNumber ( String trackingNumber );
Optional < Shipment > findByOrderId ( Long orderId );
List < Shipment > findByCarrier ( String carrier );
List < Shipment > findByCurrentStatus ( String status );
}
Document Mapping
package com.microservice.tracking.infrastructure.persistence;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.index.Indexed;
import java.time.LocalDateTime;
import java.util.List;
/**
* MongoDB document entity for shipments.
*/
@ Document ( collection = "shipments" )
public class ShipmentDocument {
@ Id
private String id ;
@ Indexed ( unique = true )
private Long orderId ;
@ Indexed ( unique = true )
private String trackingNumber ;
private String carrier ;
private LocalDateTime estimatedDelivery ;
private String currentStatus ;
private List < TrackingEventDocument > events ;
// Nested document for events
public static class TrackingEventDocument {
private String status ;
private LocalDateTime timestamp ;
private String location ;
private String details ;
private Map < String , Object > metadata ;
}
// Getters/setters...
}
Event Aggregation
MongoDB’s aggregation framework enables powerful event analytics:
/**
* Get average delivery time by carrier.
*/
public Map < String, Double > getAverageDeliveryTimesByCarrier () {
Aggregation aggregation = Aggregation . newAggregation (
match ( Criteria . where ( "currentStatus" ). is ( "Delivered" )),
project ()
. and ( "carrier" ). as ( "carrier" )
. and ( "events" ). as ( "events" ),
unwind ( "events" ),
match ( Criteria . where ( "events.status" ). is ( "Delivered" )),
group ( "carrier" )
. avg ( "events.timestamp" ). as ( "avgDeliveryTime" )
);
return mongoTemplate . aggregate (
aggregation, "shipments" , Document . class )
. getMappedResults ();
}
Architecture Pattern
com.microservice.tracking/
├── domain/
│ ├── model/
│ │ ├── Shipment.java
│ │ └── TrackingEvent.java
│ └── exception/
│ └── DomainException.java
├── application/
│ ├── port/
│ │ ├── input/
│ │ │ ├── CreateShipmentUseCase.java
│ │ │ └── AddTrackingEventUseCase.java
│ │ └── output/
│ │ └── ShipmentRepository.java
│ └── service/
│ ├── CreateShipmentService.java
│ └── TrackingEventService.java
└── infrastructure/
├── adapter/
│ ├── input/
│ │ └── rest/
│ │ └── TrackingController.java
│ └── output/
│ └── persistence/
│ ├── ShipmentDocument.java
│ ├── MongoShipmentRepository.java
│ └── ShipmentRepositoryAdapter.java
└── config/
└── MongoConfig.java
Real-Time Tracking Features
Event Streaming Implement WebSocket or Server-Sent Events for real-time status updates to customer dashboards.
Geolocation Store GPS coordinates in event metadata to display package location on maps.
Delivery Proof Store delivery photos and signatures as part of delivered event metadata.
Analytics Use MongoDB aggregation to analyze delivery performance by carrier, region, or time period.
Benefits of MongoDB for Tracking
Schema Evolution : Add new event types without database migrations
Performance : Single document read provides entire shipment history
Scalability : Horizontal sharding for high-volume tracking data
Flexibility : Different events can have completely different metadata
Developer Experience : JSON-like documents match application data structures
Future Enhancements
Event Sourcing Implement full event sourcing with event replay capabilities.
Change Streams Use MongoDB Change Streams to push real-time updates to clients.
Time-Series Data Utilize MongoDB time-series collections for IoT sensor data from delivery vehicles.
Search Integration Add Atlas Search for full-text search across event details and metadata.
Order Service Calls Tracking Service to initialize shipments
Inventory Service Triggered when stock is confirmed for shipping
Architecture Overview Learn about the overall system design