Skip to content

feat: Agnostic Persistence Layer, MongoDB Support & Rich API Timestamps#284

Closed
L7NEG wants to merge 1 commit intoPhineas:mainfrom
L7NEG:main
Closed

feat: Agnostic Persistence Layer, MongoDB Support & Rich API Timestamps#284
L7NEG wants to merge 1 commit intoPhineas:mainfrom
L7NEG:main

Conversation

@L7NEG
Copy link
Copy Markdown

@L7NEG L7NEG commented Apr 3, 2026

Lanyard Persistence & Deployment Upgrade

I have implemented a comprehensive overhaul of Lanyard's persistence layer, transforming it into a database-agnostic, production-ready system with advanced API features and infinite historical durability.


Key Features & Architectural Changes

  • Agnostic Persistence Layer: I created a new abstraction (Lanyard.Connectivity.Persistence) that handles data storage across MongoDB and Redis with intelligent fallback logic.
  • Dual-Write Strategy (Sync): When both MongoDB and Redis are provided, Lanyard uses Redis for high-speed cross-node presence synchronization while flushing KV, Last Seen, and Metrics to MongoDB for permanent durability.
  • Metrics Persistence: I've implemented a new Lanyard.Metrics.Prometheus GenServer that periodically flushes bot metrics (users monitored, socket sessions, etc.) to your database every 60 seconds.
  • Rich API Formatting:
    • Standardized timestamps: Both last_seen and monitoring_since are now rich objects containing both Unix and Raw ISO8601 strings.
    • Human Readability: I've added last_seen_readable and monitoring_since_readable fields for instant debugging.
  • Smart Monitored Since Tracker: The bot now intelligently pulls your "Monitored Since" date from the Discord Guild Join Date—exactly as seen in community bots like Shoko Makinohara.
  • Historical Recovery: The system performs a "historical sweep" across multiple database collections (monitoring, users, and kv) to ensure 2022 records are never lost.
  • Modernization: Fully updated to support Elixir 1.19 and OTP 27, resolving prior dependency conflicts with prometheus_ex.

Real-Time Sync & Persistence Specs

When deploying Lanyard, it's important to understand how different backends handle real-time cross-node synchronization versus long-term data durability.

Feature MongoDB Redis Lite Mode
Durability ✅ High ❌ Ephemeral ❌ None
Real-Time Sync ❌ No ✅ Native ❌ Local-only
KV Storage ✅ Persistent ✅ Cache-only ✅ Local-only
Bot Metrics ✅ Standard ✅ Ephemeral ❌ Not saved
Best For Infinite history High-speed global clusters Local development

Why MongoDB isn't "Real-Time" for Sync

While MongoDB is the gold standard for durability, it isn't designed for the ultra-low-latency real-time Publish/Subscribe (Pub/Sub) required to sync presence data between worldwide bot nodes instantly. MongoDB's Change Streams are powerful but are significantly heavier than Redis's native Pub/Sub engine.

What happens if I only use MongoDB?

  • Lanyard will run perfectly as a single-node durable bot.
  • All your kv, last_seen, and metrics will be persisted forever. (note: some in metrics won't as these are real-time/counters for real users ex: lanyard_connected_sessions and lanyard_monitored_users and status in {user-id} in users route)
  • The API will remain extremely fast for REST callers.
  • Note: If you scale to multiple bot nodes (e.g., globally distributed), you should add Redis to enable real-time cross-region synchronization.

Database Optionality & Fallback Logic

Lanyard can now run in three different persistence modes:

  1. Durable Mode (MongoDB): When MONGODB_URI is set, your data is stored permanently.
  2. High-Speed Mode (Redis): When REDIS_URI is set, you get high-speed cross-node presence sync.
  3. Lite Mode (In-Memory): If no database is set, the bot runs perfectly in high-performance "Lite Mode," keeping everything in memory.

API Breakdown (JSON Example)

live demo: https://rpcapi.ftp.sh/v1/users/669453086418534400

{
"data": {
"kv": {
"6": "7",
"Location": "Earth"
},
"discord_user": {
"avatar": "ebb7be6e257599994a3e29105996ad08",
"avatar_decoration_data": {
"asset": "a_c48b135704ecb5c88f2f71f6c8bcce2f",
"expires_at": null,
"sku_id": "1357589632581374042"
},
"bot": false,
"collectibles": {
"nameplate": {
"asset": "nameplates/gothica/nevermore/",
"expires_at": null,
"label": "COLLECTIBLES_GOTHICA_NEVERMORE_NP_A11Y",
"palette": "white",
"sku_id": "1462116614131548265"
}
},
"discriminator": "0",
"display_name": "L7NEG",
"display_name_styles": null,
"global_name": "L7NEG",
"id": "669453086418534400",
"primary_guild": {
"badge": null,
"identity_enabled": false,
"identity_guild_id": null,
"tag": null
},
"public_flags": 64,
"username": "l7neg"
},
"monitoring_since": {
"raw": "2022-10-01T16:22:06Z",
"unix": 1664641326
},
"activities": [],
"last_seen": {
"raw": "2026-04-03T03:07:30.417Z",
"unix": 1775185650417
},
"discord_status": "offline",
"active_on_discord_web": false,
"active_on_discord_desktop": false,
"active_on_discord_mobile": false,
"active_on_discord_embedded": false,
"active_on_discord_vr": false,
"listening_to_spotify": false,
"spotify": null,
"last_seen_readable": "April 03, 2026 03:07:30 AM",
"monitoring_since_readable": "October 01, 2022 04:22:06 PM"
},
"success": true
}

This upgrade ensures Lanyard remains the state-of-the-art presence engine for the community.

Author: L7NEG (via Antigravity)
References: Improved from PR #264 and PR #265.

Introduce MongoDB-backed persistence and migration tooling and wire it into the system. Adds Lanyard.Connectivity.MongoDB and a Persistence adapter, plus a Migration module to move API keys, KV, last_seen and metrics from Redis to MongoDB. KV and API key flows are updated to use the new Persistence/MongoDB APIs (bot commands, KV interface, API routes). Redis is made optional (graceful no-redis handling) and a Persistence fallback is used for metrics, last_seen and monitoring_since; metrics are now collected with initial values and periodically flushed from a GenServer. Dockerfile and README updated to include MongoDB in deployment examples and demonstrate durable mode; various small UX/link/message formatting and gateway/presence improvements to load persisted KV, last_seen and monitoring_since on init.
Repository owner locked and limited conversation to collaborators Apr 3, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants