Skip to main content

Prerequisites

Before you begin, ensure you have the following installed:

Node.js

Version 18.x or higher recommended

PostgreSQL

Version 12+ with PostGIS extension

MongoDB

Version 4.4+ for authentication and dispatch data

npm

Comes bundled with Node.js

Installation

1

Clone the repository

Clone the Walle repository to your local machine:
git clone <repository-url>
cd walle
2

Install dependencies

Install all required npm packages:
npm install
This will install key dependencies including:
  • @nestjs/core and @nestjs/common - NestJS framework
  • @nestjs/typeorm and typeorm - PostgreSQL ORM
  • @nestjs/mongoose and mongoose - MongoDB ODM
  • @nestjs/jwt and passport-jwt - Authentication
  • @nestjs/schedule - Cron job scheduling
  • pg - PostgreSQL driver
3

Configure environment variables

Create a .env file in the project root with the following configuration:
.env
# Server Configuration
PORT=3700

# PostgreSQL Configuration (Time-series telemetry data)
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=your_postgres_user
POSTGRES_PASSWORD=your_postgres_password
POSTGRES_DB=walledb
POSTGRES_SYNC=false

# MongoDB Configuration (User authentication)
MONGO_AUTHSOFTWARE_URI=mongodb://localhost:27017/authsoftware

# MongoDB Configuration (Dispatch data)
MONGO_DELTA_DISPATCH_URI=mongodb://localhost:27017/deltadispatch

# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
Make sure to change JWT_SECRET to a strong, random value in production environments. Never commit your .env file to version control.
The environment variable names are read from constants defined in src/common/constants/database.constant.ts and src/common/constants/settings.contant.ts.
4

Set up PostgreSQL database

Create the PostgreSQL database and enable PostGIS:
# Connect to PostgreSQL
psql -U postgres

# Create database
CREATE DATABASE walledb;

# Connect to the database
\c walledb

# Enable PostGIS extension for geospatial queries
CREATE EXTENSION IF NOT EXISTS postgis;
The partitioned points table will be created automatically when you start the application. See src/main.ts:13 and src/app/database/constants/points.sql.ts for the table schema.
5

Set up MongoDB databases

Ensure MongoDB is running and the required databases are accessible:
# Start MongoDB service
mongod

# Connect to MongoDB
mongosh

# Databases will be created automatically on first connection
# Verify connection by listing databases:
show dbs
The application will automatically create two MongoDB connections:
  • deltaDispatch - For dispatch-related data
  • authSoftware - For user authentication
6

Initialize database partitions

The application automatically creates the partitioned parent table and initial partitions on startup:
// From src/main.ts:12-15
const partitionManager = app.get(PartitionManagerService);
await partitionManager.createParentTableIfNotExists();
await partitionManager.createPartitionForDate(new Date());
await partitionManager.createPartitionForDate(new Date(Date.now() + 86_400_000));
This creates:
  • The partitioned parent table points with RANGE partitioning on timestamp
  • Today’s partition (e.g., points_20260303)
  • Tomorrow’s partition (e.g., points_20260304)
  • Indexes for timestamp, IMEI, trip ID, and geospatial location
A cron job automatically creates tomorrow’s partition every day at 23:50 to ensure uninterrupted data collection.

Running the Application

Start the application in development mode with auto-reload:
npm run start:dev
This uses the NestJS CLI command nest start --watch from package.json:12 to automatically restart the server when you make code changes.The application will start on http://localhost:3700 (or the port specified in your .env file).

Verify Installation

Check the console output to confirm successful startup:
[Nest] 12345  - 03/03/2026, 10:30:00 AM     LOG [NestFactory] Starting Nest application...
[Nest] 12345  - 03/03/2026, 10:30:01 AM     LOG [InstanceLoader] AppModule dependencies initialized
[Nest] 12345  - 03/03/2026, 10:30:01 AM     LOG [InstanceLoader] TypeOrmModule dependencies initialized
[Nest] 12345  - 03/03/2026, 10:30:01 AM     LOG [InstanceLoader] MongooseModule dependencies initialized
[Nest] 12345  - 03/03/2026, 10:30:02 AM     LOG [PartitionManagerService] Partitioned parent table points created.
[Nest] 12345  - 03/03/2026, 10:30:02 AM     LOG [PartitionManagerService] Partition points_20260303 created with all indexes.
[Nest] 12345  - 03/03/2026, 10:30:02 AM     LOG [PartitionManagerService] Partition points_20260304 created with all indexes.
[Nest] 12345  - 03/03/2026, 10:30:02 AM     LOG [NestApplication] Nest application successfully started

Using the Service Layer

Walle provides a complete backend infrastructure with services, models, and partition management. The HTTP API layer (controllers with endpoints) is not yet implemented, but you can use the services directly in your NestJS application.
1

Inject and use PointsService

The PointsService provides access to the partitioned Point repository. Here’s how to use it in your own controller or service:
import { Injectable } from '@nestjs/common';
import { PointsService } from './app/points/points.service';
import { Point } from './app/points/model/point.model';

@Injectable()
export class YourService {
  constructor(private readonly pointsService: PointsService) {}
  
  async createPoint(pointData: Partial<Point>) {
    // The PointsService has access to the TypeORM repository
    // You can extend it with your own methods
    const point = await this.pointsService.pointsRepository.save({
      timestamp: Date.now(),
      trackerDeviceImei: 123456789012345,
      trackerDeviceLatitude: -12.0464,
      trackerDeviceLongitude: -77.0428,
      ...pointData
    });
    return point;
  }
}
The PointsService is defined in src/app/points/points.service.ts and provides the TypeORM repository for the Point entity. You’ll need to add your own business logic methods.
2

Work with the Point model

The Point entity includes 50+ fields for complete vehicle telemetry tracking (defined in src/app/points/model/point.model.ts):Required fields:
  • id - UUID (auto-generated)
  • timestamp - Unix timestamp in milliseconds (bigint)
  • trackerDeviceImei - Device IMEI number
  • trackerDeviceLatitude - GPS latitude
  • trackerDeviceLongitude - GPS longitude
Optional tracking fields:
  • location - PostGIS Point geometry (SRID 4326)
  • trackerDeviceSpeedKh - Speed in km/h
  • trackerDeviceAngle - Direction angle
  • trackerDeviceIgnition - Engine on/off state
  • trackerDeviceNumberOfSatellites - GNSS satellite count
The Point model uses a composite primary key (id, timestamp) required by PostgreSQL range partitioning. Both fields must be provided when creating records.
3

Use authentication infrastructure

Walle includes JWT authentication infrastructure using JwtStrategy and JwtAuthguard:
import { Controller, Get } from '@nestjs/common';
import { Auth } from './common/decorators/auth.decorator';
import { User } from './common/decorators/user.decorator';

@Controller('your-endpoint')
export class YourController {
  
  @Get()
  @Auth()  // Apply JWT authentication guard
  async protectedRoute(@User() user) {
    // user is populated by JwtStrategy.validate()
    // which looks up the user by user_dni from the JWT payload
    return { message: 'Authenticated', userId: user._id };
  }
}
The @Auth() decorator (from src/common/decorators/auth.decorator.ts) applies the JwtAuthguard, which validates JWT tokens and populates the user via JwtStrategy.validate() from src/app/auth/strategies/jwt.strategy.ts.

Understanding Partition Management

Walle uses time-series partitioning to efficiently manage high-volume GPS data:

Automatic Daily Partitions

Partitions are automatically created using the naming pattern points_YYYYMMDD:
-- Example partition for March 3, 2026
CREATE TABLE points_20260303
  PARTITION OF points
  FOR VALUES FROM (1709424000000) TO (1709510400000)

Partition Indexes

Each partition includes optimized indexes defined in src/app/points/partition-manager.service.ts:67-84:
  • idx_points_YYYYMMDD_timestamp - Time-range queries
  • idx_points_YYYYMMDD_imei_ts - Device-specific queries
  • idx_points_YYYYMMDD_imei_ts_trip - Trip tracking queries
  • idx_points_YYYYMMDD_location - Geospatial queries (GIST index)

Scheduled Partition Creation

A cron job runs daily at 23:50 to create tomorrow’s partition:
// From src/app/points/partition-manager.service.ts:111-116
@Cron('50 23 * * *')
async scheduleNextDay(): Promise<void> {
  const tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  await this.createPartitionForDate(tomorrow);
}

Next Steps

Architecture

Learn about Walle’s multi-database architecture and design decisions

Point Data Model

Explore all 50+ fields available in the Point entity

Partition Management

Deep dive into partition creation, maintenance, and cleanup

Authentication

Understand JWT authentication and user management

Build docs developers (and LLMs) love