Local Deployment Guide on Mojaloop Platform Components
This document reflects the local non-Kubernetes deployment maintained under Project:
👉 Mojaloop Local Deployment Repository
⚠️ Scope Notice
This deployment guide is intended for local development, testing, and learning purposes only. It is not production-hardened and does not include:
- High availability (HA)
- Horizontal scaling
- TLS/mTLS enforcement
- Network isolation
- Observability stack (Prometheus, Grafana, etc.)
For production deployments, refer to the Platform Architecture and Security Architecture documentation.
Introduction
Mojaloop is an open-source platform that provides interoperable digital payment infrastructure. It was created by the Mojaloop Foundation to address the challenge of siloed payment systems that limit financial inclusion, particularly in emerging markets and underbanked regions. By offering a set of open standards and software, Mojaloop enables different financial service providers (FSPs) to connect and transact seamlessly — lowering costs and expanding access to digital financial services.
This repository, which is part of Project MELODY, provides a guide and configuration for deploying Mojaloop's core platform services locally, without Kubernetes or Helm. It is intended for development, testing, and learning purposes.
Platform Components
The core Mojaloop services included in this deployment are located in the platform/ folder. Each subfolder contains the source for a specific version/tag of the component.
| Component | Version | Description |
|---|---|---|
| account-lookup-service | 17.14.4 |
Handles participant discovery and routing. Maintains a registry of FSPs and their endpoints so the switch can locate the correct recipient institution for a payment. |
| quoting-service | 17.13.8 |
Calculates fees and FSP commissions for interoperable transactions, giving both payer and payee FSPs a complete view of all costs involved. |
| central-ledger | 19.11.3 |
The core ledger that manages transfers between participating institutions. Provides real-time clearing messages, maintains account positions, and handles scheme-level fees. |
| central-settlement | 17.2.6 |
Manages settlement between FSPs and the central hub. Administers settlement windows, event triggers, and FSP account details. |
| ml-api-adapter | 16.6.1 |
A translation layer that converts between the Mojaloop API and the internal format used by the Central Services stack. |
| sdk-scheme-adapter | 0.0.70 |
Bridges non-Mojaloop-compliant DFSP backends with the Mojaloop switch by translating synchronous HTTP calls into native Mojaloop API interactions. |
Infrastructure Tools
Mojaloop's platform services depend on several infrastructure tools. Configuration and scripts for each are provided in the tools/ folder.
| Tool | Folder | Purpose |
|---|---|---|
| Apache Kafka | tools/kafka/ |
Message broker for asynchronous event streaming between services. |
| Redis | tools/redis/ |
In-memory data store used as a distributed cache (runs as a 6-node cluster). |
| MySQL | tools/mysql/ |
Relational database for central-ledger, quoting-service, and account-lookup-service. |
| Redpanda | tools/redpanda/ |
Kafka-compatible streaming platform (alternative to Apache Kafka). |
Additional Tools
| Tool | Folder | Purpose |
|---|---|---|
| Postman | tools/postman/ |
API collection (Melody.postman_collection.json) for testing Mojaloop endpoints. |
| JMeter | tools/jmeter/ |
Performance/load testing scripts for wallet-to-wallet transfers. |
Setup Guide
1. Kafka
Mojaloop uses Apache Kafka (in KRaft mode — no ZooKeeper) for event streaming between services. Download Kafka from https://dlcdn.apache.org/kafka/3.9.1/kafka_2.12-3.9.1.tgz.
1.1 Configure
Copy the provided server.properties into your Kafka installation:
cp tools/kafka/server.properties <KAFKA_HOME>/config/server.properties
Key settings in the provided configuration:
| Setting | Value | Notes |
|---|---|---|
process.roles |
broker,controller |
Runs in KRaft mode (combined broker + controller) |
listeners |
INTERNAL://0.0.0.0:9092, EXTERNAL://0.0.0.0:9094, CONTROLLER://localhost:9093 |
Internal for local services, External for Docker containers |
advertised.listeners |
INTERNAL://localhost:9092, EXTERNAL://host.docker.internal:9094 |
Docker services connect via host.docker.internal:9094 |
log.dirs |
/home/mojaloop/storage |
Update this to your preferred data directory |
1.2 Initialize and Start
# From your Kafka installation directory:
# Initialize the storage (first time only)
./tools/kafka/scripts/init-kafka.sh
# Start the broker
./tools/kafka/scripts/start-kafka.sh
1.3 Create Topics
Mojaloop requires a set of predefined Kafka topics. Create them with:
./tools/kafka/scripts/create-topics.sh [KAFKA_HOST] [KAFKA_PORT]
# Defaults to localhost:9092 if no arguments given
This creates the following topics (replication-factor=1, partitions=1):
| Category | Topics |
|---|---|
| Transfers | topic-transfer-prepare, topic-transfer-position, topic-transfer-fulfil, topic-transfer-get, topic-transfer-position-batch |
| Admin | topic-admin-transfer |
| Notifications | topic-notification-event |
| Bulk | topic-bulk-prepare, topic-bulk-fulfil, topic-bulk-processing, topic-bulk-get |
| Quotes | topic-quotes-post, topic-quotes-put, topic-quotes-get |
| FX Quotes | topic-fx-quotes-post, topic-fx-quotes-put, topic-fx-quotes-get |
| Bulk Quotes | topic-bulkquotes-post, topic-bulkquotes-put, topic-bulkquotes-get |
| Settlement | topic-deferredsettlement-close |
1.4 Utility Scripts
| Script | Purpose |
|---|---|
tools/kafka/scripts/list-group-details.sh |
Lists consumer group lag and offsets for all Mojaloop consumer groups |
tools/kafka/scripts/remove-all-topics.sh |
Deletes all non-internal topics (useful for a clean reset) |
1.5 Redpanda Console (Optional)
For a web UI to inspect Kafka topics, consumer groups, and messages, you can run the Redpanda Console:
docker compose -f tools/redpanda/docker-compose.yml up -d
The console will be available at http://localhost:18080. It connects to Kafka via host.docker.internal:9094 (the EXTERNAL listener).
2. Redis Cluster
Mojaloop uses a Redis cluster as a distributed cache. The provided script sets up a 3-node cluster locally.
Prerequisites: Redis 7 must be installed. Ensure redis-server and redis-cli are available on your PATH.
2.1 Start the Cluster
cd tools/redis
./start-redis-cluster.sh
This will:
1. Create a redis-cluster/ directory with per-node configuration and data
2. Start 3 Redis instances on ports 6379, 6380, and 6381
3. Form them into a cluster with --cluster-replicas 0 (no replicas, masters only)
Each node runs with cluster-enabled yes, appendonly yes, and protected-mode no.
2.2 Stop the Cluster
cd tools/redis
./stop-redis-cluster.sh
This shuts down all 3 nodes (ports 6379–6381) gracefully.
3. MySQL
Mojaloop's central-ledger, quoting-service, and account-lookup-service store data in MySQL. Version 8.4 or lower is supported (Mojaloop recommends 5.7).
3.1 Configure
Use the provided my.cnf as a template:
[mysqld]
basedir=/<your_mysql_location>
datadir=/<your_mysql_location>/data
socket=/tmp/mysql.sock
port=3306
mysql_native_password=ON
Important: If using MySQL 8.4+, the
mysql_native_password=ONsetting is required because Mojaloop's database libraries rely on themysql_native_passwordauthentication plugin.
3.2 Create the Database User
-- Create the user (or alter if it already exists)
ALTER USER 'central_ledger'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
-- Grant full privileges (required for Knex DB migrations)
GRANT ALL PRIVILEGES ON *.* TO 'central_ledger'@'%';
FLUSH PRIVILEGES;
central_ledger is the default username used by Mojaloop services. You can change it, but you will need to update the service configurations accordingly.
4. Running Platform Services
Prerequisites: Ensure Kafka, Redis, and MySQL are running before starting any platform service.
Each service is pre-configured with a default.json that points to the local infrastructure tools (Kafka at localhost:9092, Redis at localhost:6379, MySQL at localhost:3306). If you are using the same settings from the setup steps above, no configuration changes are needed.
Services should be started in the following order:
4.1 Central Ledger
The central-ledger is the core service and must be started first, as other services depend on it.
cd platform/central-ledger-19.11.3
npm install
npm run start:api
| Setting | Value |
|---|---|
| API Port | 3001 |
| MySQL User / Schema | central_ledger / central_ledger |
| Config | platform/central-ledger-19.11.3/config/default.json |
On first run, Knex will automatically run database migrations (
MIGRATIONS.DISABLED: false).
4.2 Account Lookup Service
cd platform/account-lookup-service-17.14.4
npm install
npm run start:all
| Setting | Value |
|---|---|
| Admin Port | 4001 |
| API Port | 4002 |
| Monitoring Port | 4003 |
| MySQL User / Schema | account_lookup / account_lookup |
| Config | platform/account-lookup-service-17.14.4/config/default.json |
This service uses a separate MySQL user (
account_lookup). Make sure to create it the same way ascentral_ledger(see Section 3.2).
4.3 Quoting Service (API)
cd platform/quoting-service-17.13.8
npm install
npm run start:api
| Setting | Value |
|---|---|
| API Port | 3002 |
| Monitoring Port | 3003 |
| MySQL User / Schema | central_ledger / central_ledger |
| Config | platform/quoting-service-17.13.8/config/default.json |
4.4 Quoting Service (Handlers)
In a separate terminal, start the Kafka consumer handlers for the quoting service:
cd platform/quoting-service-17.13.8
npm run start:handlers
The handlers consume from Kafka topics (
topic-quotes-*,topic-bulkquotes-*,topic-fx-quotes-*) and process quote requests asynchronously.npm installis not needed again if already done in step 4.3.
4.5 ML API Adapter
cd platform/ml-api-adapter-16.6.1
npm install
npm run start:api
| Setting | Value |
|---|---|
| API Port | 3000 |
| Central Ledger Endpoint | http://localhost:3001 |
| Config | platform/ml-api-adapter-16.6.1/config/default.json |
This is the main entry point for FSPIOP API calls. It forwards transfer requests to the central-ledger via Kafka.
4.6 Central Settlement
cd platform/central-settlement-17.2.6
npm install
npm run start:api
| Setting | Value |
|---|---|
| API Port | 3007 |
| MySQL User / Schema | central_ledger / central_ledger |
| Central Ledger Endpoint | http://localhost:3001 |
| Config | platform/central-settlement-17.2.6/config/default.json |
5. Building and Running the Simulator
The simulator provides two wallet instances (wallet1 and wallet2) that act as DFSPs, allowing you to test end-to-end transfers through the Mojaloop platform.
The simulator's Connector component is production-grade and can be used as the foundation for connecting your FSP to Mojaloop. It reduces one network hop compared to the standard approach:
| Approach | Flow | Hops to Hub |
|---|---|---|
| Connector (recommended) | FSP → Connector → Hub | 2 |
| sdk-scheme-adapter | FSP → Core Connector → sdk-scheme-adapter → Hub | 3 |
Both approaches work, but if you want a leaner integration, the Connector provides a more direct path. Alternatively, you can use the sdk-scheme-adapter with a Core Connector if that better suits your architecture.
Note: If you need ready-made features such as mTLS, transaction logging, and a management portal, consider using PM4ML (Payment Manager for Mojaloop), which already bundles a Core Connector and sdk-scheme-adapter out of the box.
Prerequisites: Apache Maven and JDK 21 (or 25) must be installed.
5.1 Build the Simulator
cd simulator
mvn install -DskipTests=true
5.2 Prepare the Wallets
After the build completes, copy the connector JAR and its dependencies into the wallets/ folder:
mkdir -p wallets/lib
cp simulator/connector/target/mod_connector-1.0.0.jar wallets/
cp simulator/connector/target/lib/* wallets/lib/
Your wallets/ folder should look like this:
wallets/
├── mod_connector-1.0.0.jar
├── lib/ # dependency JARs
├── wallet1.sh
├── wallet1-log4j2.xml
├── wallet2.sh
└── wallet2-log4j2.xml
5.3 Run the Wallets
Start each wallet in a separate terminal:
# Terminal 1 — Wallet 1
cd wallets
./wallet1.sh
# Terminal 2 — Wallet 2
cd wallets
./wallet2.sh
| Wallet | FSP ID | Inbound Port | Outbound Port |
|---|---|---|---|
| Wallet 1 | wallet1 |
8081 |
8080 |
| Wallet 2 | wallet2 |
9091 |
9090 |
Both wallets connect to the platform services at their default local ports (account-lookup on 4002, quoting-service on 3002, ml-api-adapter on 3000).
6. Onboarding Wallets
Once all platform services and wallets are running, you need to onboard the wallets (DFSPs) onto the Mojaloop hub. This is done using the Postman collection at tools/postman/Melody.postman_collection.json.
Prerequisites: Import the collection into Postman.
6.1 Setup the Hub
Open the onboarding > create-hub folder in the Postman collection and run each request in order:
list enums— verify the hub is reachablesetup-HUB_MULTILATERAL_SETTLEMENT— create the multilateral settlement accountsetup-HUB_RECONCILIATION— create the reconciliation accountcreate settlement model— configure the settlement modeladd Oracle(optional) — register the an oracle for party lookups. Skip this if you do not have Oracle.get Oracles(optional) — verify the oracle was registered
6.2 Create Participants
Open the onboarding > create-participants folder. Run the requests for wallet1 and wallet2 (steps 1–4 in order):
For each wallet:
| Step | Request | Purpose |
|---|---|---|
| 1 | create new participant |
Register the DFSP with the hub |
| 2 | activate POSITION account |
Activate the position account |
| 3 | create limit and position |
Set the Net Debit Cap (NDC) limit |
| 4 | fund In to SETTLEMENT account |
Fund the settlement account |
After creating participants, proceed to Section 6.3 to register the callback endpoints for wallet1 and wallet2.
6.3 Register Wallet Endpoints
After completing the Postman steps above, run the endpoint registration scripts to register all FSPIOP callback URLs for each wallet:
./onboarding/register-wallet1-endpoints.sh
./onboarding/register-wallet2-endpoints.sh
These scripts register callback endpoints (parties, quotes, transfers, bulk operations, etc.) against the central-ledger, pointing to each wallet's outbound port:
| Wallet | Callback Base URL |
|---|---|
| Wallet 1 | http://localhost:8080 |
| Wallet 2 | http://localhost:9090 |
After this step, both wallets are fully onboarded and ready to send/receive transfers through the Mojaloop platform.
7. Performing Transfers
With all services running and wallets onboarded, you can perform end-to-end transfers using Apache JMeter.
Prerequisites: JDK 21 (or 25) and Apache JMeter 5.6.3 must be installed.
7.1 Run a Transfer Test
- Open Apache JMeter
- Load the test plan: File > Open →
tools/jmeter/wallet1-to-wallet2.jmx - Click the Start button (▶) to run the test
The test plan sends transfers from wallet1 to wallet2 through the full Mojaloop flow (party lookup → quote → transfer). By default it runs with 1 thread and 100 iterations.
| Setting | Value |
|---|---|
| Payer FSP | wallet1 |
| Payee FSP | wallet2 |
| Target | http://localhost:8081 (wallet1 inbound) |
| Threads | 1 |
| Loop Count | 100 |
A reverse test plan (
wallet2-to-wallet1.jmx) is also available in the same folder for testing transfers in the opposite direction.
8. Settlement
After performing transfers, you can settle the net positions between participants. The settlement process is available in the Postman collection under the settlement folder.
Follow these steps in order:
8.1 Close the Current Settlement Window
Close the currently open settlement window so that all completed transfers are captured for settlement.
8.2 Create the Settlement
Create a new settlement to calculate the net amounts to be settled between participants. This will show how much each FSP owes or is owed based on the transfers that occurred within the closed window.
8.3 Update the Settlement Status
Update the settlement status to progress it through the settlement lifecycle (e.g., from PENDING_SETTLEMENT to PS_TRANSFERS_RECORDED to PS_TRANSFERS_COMMITTED).
8.4 Deposit or Withdraw Funds
Based on the net settlement amounts from step 8.2: - Deposit funds into the settlement account for FSPs that owe money (net debtors) - Withdraw funds from the settlement account for FSPs that are owed money (net creditors)
This final step reconciles the actual fund movements and completes the settlement cycle.
Port Summary
| Service | Port(s) |
|---|---|
| ml-api-adapter | 3000 |
| central-ledger | 3001 |
| quoting-service (API) | 3002 |
| quoting-service (Monitoring) | 3003 |
| central-settlement | 3007 |
| account-lookup-service (Admin) | 4001 |
| account-lookup-service (API) | 4002 |
| account-lookup-service (Monitoring) | 4003 |
| Wallet 1 (Inbound / Outbound) | 8081 / 8080 |
| Wallet 2 (Inbound / Outbound) | 9091 / 9090 |