Backend API for a real-time system built with Kotlin and Ktor.
This service manages authentication, user relationships, shared state, and real-time communication with fallback delivery using WebSockets and Firebase Cloud Messaging (FCM).
This backend is the core of the Signus system, responsible for:
- user authentication and identity
- linking between two users
- shared "semaphore" state (
AVAILABLE,BUSY,OFFLINE) - real-time event delivery via WebSocket
- fallback delivery via FCM when realtime is not available
Signus is structured as a multi-repository system:
- signus_app — Android client
- signus_back — Backend API (this repository)
- signus_infra — Infrastructure and deployment
- Designing a backend for real-time user-to-user communication
- Implementing WebSocket-based event delivery
- Building a fallback system (WebSocket → Push notifications)
- Managing state synchronization between distributed clients
- Structuring a backend using feature-based architecture
- Integrating JWT authentication, persistence, and messaging systems
The backend follows a feature-based modular structure:
routes → services → repositories → database
Project layout:
src/main/kotlin/
core/
features/
auth/
devicetoken/
linking/
notification/
semaphore/
user/
- routes → HTTP / WebSocket endpoints, validation, auth extraction
- services → business logic and orchestration
- repositories → persistence and DB mapping
- core → shared infrastructure (config, DI, security, DB)
This system is built around a hybrid real-time communication strategy.
-
Each authenticated user can open a WebSocket session:
WS /ws?token=<jwt> -
The backend pushes events directly to connected clients
If real-time delivery is not possible:
- no active WebSocket session
- app is in background
- connection lost
👉 the backend automatically falls back to push notifications via FCM
- WebSocket = low-latency realtime
- FCM = delivery guarantee when realtime is unavailable
👉 This ensures the system remains consistent even when clients are offline.
The backend emits domain events to clients:
{
"type": "PARTNER_STATUS_CHANGED",
"partnerId": "user-1",
"status": "AVAILABLE",
"statusExpiration": null,
"timestamp": 1710930000000
}{
"type": "PARTNER_UNLINKED",
"partnerId": "user-1",
"timestamp": 1710930000000
}- User A creates a linking session
- Backend generates
linkCode - User B confirms the session
- Backend links both users
- Client calls
PATCH /status - Backend persists the new state
- Backend attempts WebSocket delivery
- If it fails → fallback to FCM
- Client calls
DELETE /partner - Backend removes relationship
- Emits
PARTNER_UNLINKEDevent if possible
- Kotlin
- Ktor
- PostgreSQL
- Exposed
- Flyway
- Koin
- JWT
- WebSockets
- Firebase Cloud Messaging (FCM)
- Docker / Docker Compose
- Testcontainers
-
JWT-based authentication
-
Protected endpoints require:
Authorization: Bearer <jwt> -
WebSocket authentication via query param
-
Secrets managed via environment variables
Copy:
cp .env.example .envConfigure:
- database credentials
- JWT configuration
- FCM server key
- port
docker compose up --builddocker compose up -d db
./gradlew runBase URL:
- HTTP →
http://localhost:8080 - WS →
ws://localhost:8080
Main domains:
- authentication (
/auth) - linking (
/linking) - user (
/me,/partner) - status (
/status) - device tokens (
/devices/fcm-token) - realtime (
/ws)
- Real-time backend with graceful degradation
- Clear separation of concerns across layers
- Explicit handling of connection vs delivery guarantees
- WebSocket + FCM hybrid strategy
- Feature-based architecture for scalability
- Backend-driven state consistency
This project is source-available but not open source.
You may view and study the code, but you are not allowed to:
- use it for commercial purposes
- deploy it as a service
- build competing products
See LICENSE for details.
E-delSol