Regional Service
Overview
Section titled “Overview”The Regional Service provides access to Indonesian administrative region data (province, city, district, village). It is implemented as a separate service (merq-indonesian-regional) with its own PostgreSQL database containing reg_* tables.
The main backend (merq-backend) proxies requests to the regional service via HTTP. This separation allows independent scaling and maintenance of the regional data service.
Use cases:
- Outlet store location assignment
- Employee address registration
- Geographic filtering and reporting
Architecture
Section titled “Architecture”sequenceDiagram
participant Web as Web/Mobile Client
participant Backend as merq-backend (proxy)
participant Regional as merq-indonesian-regional
Web->>Backend: GET /office/v1/regional/provinces
Backend->>Regional: HTTP GET /provinces
Regional-->>Backend: JSON response
Backend-->>Web: Proxy response
Note over Backend,Regional: Separate DB, same Docker network
Key Points:
- Regional service runs as a separate HTTP service
merq-backendproxies requests (no direct DB access)- Both services run in the same Docker network (Dokploy)
- Configured via
REGIONAL_SERVICE_URLenvironment variable
Data Model
Section titled “Data Model”RegionalItem
Section titled “RegionalItem”| Field | Type | Description |
|---|---|---|
| id | integer | Primary key |
| code | string | Regional code (e.g., “31” for Jakarta) |
| name | string | Regional name (e.g., “DKI Jakarta”) |
| type | string | Only for cities: “kota” or “kabupaten” |
API Endpoints
Section titled “API Endpoints”All endpoints are read-only (no RBAC required beyond authentication).
| Method | Endpoint | Description | Params |
|---|---|---|---|
| GET | /office/v1/regional/provinces | List all provinces | page, limit, keyword |
| GET | /office/v1/regional/cities | List cities by province | province_id (required), page, limit, keyword |
| GET | /office/v1/regional/districts | List districts by city | city_id (required), page, limit, keyword |
| GET | /office/v1/regional/villages | List villages by district | district_id (required), page, limit, keyword |
Mobile endpoints:
Same paths under /app/v1/regional/ prefix (read-only).
Example Requests and Responses
Section titled “Example Requests and Responses”Provinces
Section titled “Provinces”GET /office/v1/regional/provinces?keyword=Jakarta{ "data": [ { "id": 31, "code": "31", "name": "DKI Jakarta" } ], "message": "provinces retrieved", "code": "PROVINCE_LIST"}Cities
Section titled “Cities”GET /office/v1/regional/cities?province_id=31{ "data": [ { "id": 3171, "code": "3171", "name": "Jakarta Pusat", "type": "kota" }, { "id": 3172, "code": "3172", "name": "Jakarta Utara", "type": "kota" } ], "message": "cities retrieved", "code": "CITY_LIST"}Districts
Section titled “Districts”GET /office/v1/regional/districts?city_id=3171{ "data": [ { "id": 317101, "code": "317101", "name": "Gambir" }, { "id": 317102, "code": "317102", "name": "Tanah Abang" } ], "message": "districts retrieved", "code": "DISTRICT_LIST"}Villages
Section titled “Villages”GET /office/v1/regional/villages?district_id=317101{ "data": [ { "id": 3171010001, "code": "3171010001", "name": "Gambir" }, { "id": 3171010002, "code": "3171010002", "name": "Kebon Kelapa" } ], "message": "villages retrieved", "code": "VILLAGE_LIST"}Cascade Selection Pattern
Section titled “Cascade Selection Pattern”The regional API is designed for cascading dropdowns:
1. Load Provinces (no parent) ↓ user selects province2. Load Cities (filter by province_id) ↓ user selects city3. Load Districts (filter by city_id) ↓ user selects district4. Load Villages (filter by district_id)Important:
- Always load parent first
- Child lists are empty until parent is selected
- Reset child selections when parent changes
- Village table has 83k+ rows — always require
district_idfilter
Configuration
Section titled “Configuration”Environment Variables
Section titled “Environment Variables”| Variable | Default | Description |
|---|---|---|
REGIONAL_SERVICE_URL | http://merq-indonesian-regional:8081 | Regional service base URL |
Local Development
Section titled “Local Development”For local development, set in .env:
REGIONAL_SERVICE_URL=http://localhost:8082Production
Section titled “Production”In Dokploy, services are in the same Docker network:
REGIONAL_SERVICE_URL=http://merq-indonesian-regional:8081Error Handling
Section titled “Error Handling”Regional Service Unreachable
Section titled “Regional Service Unreachable”If the regional service is down, the backend returns empty data (graceful degradation):
{ "data": [], "message": "regional service unavailable", "code": "REGIONAL_SERVICE_ERROR"}Invalid Parent ID
Section titled “Invalid Parent ID”If parent ID doesn’t exist:
{ "data": [], "message": "province not found", "code": "REGIONAL_PROVINCE_NOT_FOUND"}HTTP Status Codes:
200 OK— Success404 Not Found— Parent ID not found503 Service Unavailable— Regional service down
Data Volume
Section titled “Data Volume”| Level | Count | Notes |
|---|---|---|
| Provinces | ~34 | All Indonesian provinces |
| Cities | ~514 | Kota + Kabupaten |
| Districts | ~7,200 | Kecamatan |
| Villages | ~83,000+ | Kelurahan/Desa |
Performance Notes:
- Province/city lists are small (can load all)
- District/village lists require parent filter
- Keyword search recommended for large lists