Skip to content

TD-001: Telegram + WealthOS Migration to integrations Table

Status: Identified Priority: Medium Estimated Effort: 3-4 days (Telegram: 2 days, WealthOS: 1-2 days) Date Identified: 2025-11-10 Identified By: root (during Threema integration planning)


Description

What: Telegram and WealthOS integrations currently use fields directly in the user table instead of the unified integrations table pattern established for Threema.

Current State:

# backend/app/models.py
class User(UserBase, table=True):
    # Telegram integration (LEGACY PATTERN - notification channel)
    telegram_verification_code: str | None = Field(default=None, max_length=4)
    telegram_chat_id: str | None = Field(default=None, max_length=50)
    telegram_connected_at: datetime | None = Field(default=None)

    # WealthOS integration (LEGACY PATTERN - data source)
    wealthos_api_key: str | None = Field(default=None, max_length=255)
    wealthos_connected_at: datetime | None = Field(default=None)

Desired State:

# Telegram as UserIntegration (same as Threema)
UserIntegration(
    user_id=user.id,
    integration_type=IntegrationType.TELEGRAM,
    config={
        "chat_id": telegram_chat_id,
        "verification_code": verification_code
    },
    connected_at=telegram_connected_at,
    is_active=True
)

# WealthOS as UserIntegration
UserIntegration(
    user_id=user.id,
    integration_type=IntegrationType.WEALTHOS,
    config={
        "api_key": wealthos_api_key,
        "last_sync_at": None  # or actual timestamp
    },
    connected_at=wealthos_connected_at,
    is_active=True
)

Why It Exists: - Telegram and WealthOS were implemented before the unified integrations table existed - During Threema integration, we chose pragmatic approach: implement correct pattern for new integrations, defer Telegram/WealthOS refactoring to avoid risk

Impact

Maintainability

  • ⚠️ Inconsistent Patterns: Developers must learn different ways to query integrations (Telegram/WealthOS in User table, Threema in integrations table)
  • ⚠️ Code Duplication: Different query logic for Telegram/WealthOS vs. Threema
  • ⚠️ Documentation Burden: Need to explain why three patterns exist (Telegram fields, WealthOS fields, integrations table)

Scalability

  • ⚠️ User Table Growth: Telegram + WealthOS fields stay in User table (6 fields total)
  • ⚠️ Query Inconsistency: "Get all users with integration X" works differently for legacy integrations vs. new ones

Performance

  • No Impact: Current Telegram implementation performs fine
  • Minor Benefit: Migration would allow consistent indexed queries

Security

  • No Impact: No security implications

Overall Impact: Low to Medium - System works fine, but code inconsistency creates maintenance burden.

Remediation Plan

Prerequisites

  1. Verify notification_channels table is working well with Threema (wait 1-2 months post-Threema launch)
  2. Ensure no active Telegram-related bugs or issues
  3. Get approval from tech lead

Implementation Steps

Phase 1: Preparation (4 hours) 1. Document current Telegram user count:

SELECT COUNT(*) FROM "user" WHERE telegram_chat_id IS NOT NULL;
2. Create backup of User table 3. Create migration plan document 4. Write comprehensive tests for Telegram functionality

Phase 2: Dual-Write Pattern (4 hours) 1. Update TelegramRegistrationService to write to BOTH: - Legacy User fields (backward compatibility) - New notification_channels table 2. Deploy and monitor for 1 week 3. Verify both data stores stay in sync

Phase 3: Read Migration (2 hours) 1. Update TelegramChannel to read from notification_channels table 2. Fallback to User table if not found (backward compatibility) 3. Deploy and monitor

Phase 4: Data Migration (3 hours) 1. Create Alembic migration to copy existing Telegram and WealthOS data:

-- Migrate Telegram connections
INSERT INTO integrations (
    user_id, integration_type, config, connected_at, is_active
)
SELECT
    id,
    'telegram',
    jsonb_build_object(
        'chat_id', telegram_chat_id,
        'verification_code', telegram_verification_code
    ),
    COALESCE(telegram_connected_at, NOW()),
    TRUE
FROM "user"
WHERE telegram_chat_id IS NOT NULL;

-- Migrate WealthOS connections
INSERT INTO integrations (
    user_id, integration_type, config, connected_at, is_active
)
SELECT
    id,
    'wealthos',
    jsonb_build_object(
        'api_key', wealthos_api_key
    ),
    COALESCE(wealthos_connected_at, NOW()),
    TRUE
FROM "user"
WHERE wealthos_api_key IS NOT NULL;
2. Run in staging, verify data integrity 3. Run in production, verify all users migrated 4. Verify counts match:
-- Before migration
SELECT COUNT(*) FROM "user" WHERE telegram_chat_id IS NOT NULL;
SELECT COUNT(*) FROM "user" WHERE wealthos_api_key IS NOT NULL;

-- After migration
SELECT COUNT(*) FROM integrations WHERE integration_type = 'telegram';
SELECT COUNT(*) FROM integrations WHERE integration_type = 'wealthos';

Phase 5: Cleanup (2 hours) 1. Remove fallback logic (now reads only from notification_channels) 2. Remove dual-write (writes only to notification_channels) 3. Deploy and monitor for 1 week

Phase 6: Schema Cleanup (2 hours) 1. Create Alembic migration to drop old columns:

ALTER TABLE "user"
DROP COLUMN telegram_verification_code,
DROP COLUMN telegram_chat_id,
DROP COLUMN telegram_connected_at,
DROP COLUMN wealthos_api_key,
DROP COLUMN wealthos_connected_at;
2. Run in staging 3. Run in production 4. Archive this TD as "Resolved"

Total Estimated Effort: 16-18 hours (~2-3 days)

Rollback Plan

Each phase is independently reversible: - Phase 2-3: Just rollback code deployment - Phase 4: Delete rows from notification_channels where channel_type='telegram' - Phase 5-6: Restore User table columns from backup

Priority Justification

Priority: Medium (not High or Low)

Why Not High? - ✅ Current Telegram implementation works fine - ✅ No user-facing impact - ✅ No security/performance issues - ✅ Can wait 1-2 months post-Threema launch

Why Not Low? - ⚠️ Code inconsistency creates maintenance burden - ⚠️ Future channels will follow notification_channels pattern (divergence grows) - ⚠️ Developer confusion risk (two patterns)

When to Increase Priority: - If adding a 3rd channel (WhatsApp, Signal) - then High priority to standardize - If Telegram bugs emerge from dual-pattern confusion - then High priority - If codebase becomes difficult to onboard new developers - then High priority

Success Criteria

✅ All existing Telegram users still connected and working ✅ All existing WealthOS users still connected and working ✅ New Telegram registrations use integrations table ✅ New WealthOS connections use integrations table ✅ TelegramChannel service uses same query pattern as ThreemaChannel ✅ WealthOS service uses same query pattern as Threema ✅ User table no longer has telegram_ or wealthos_ fields ✅ All tests pass ✅ No Telegram-related bug reports for 2 weeks post-migration ✅ No WealthOS-related bug reports for 2 weeks post-migration

  • ADR-001: Unified Integrations Table Architecture (explains why this TD exists)
  • Code References:
  • backend/app/models.py lines 67-74 (Telegram and WealthOS fields to remove)
  • backend/app/api/services/signals/telegram_registration_service.py (update to use integrations table)
  • backend/app/api/services/signals/notification_channels/telegram_channel.py (update queries)
  • WealthOS services (need to identify and update)
  • Migration: Will create backend/app/alembic/versions/[timestamp]_migrate_telegram_wealthos_to_integrations.py

Status Updates

  • 2025-11-10: Technical debt identified during Threema integration planning
  • Future: When starting work, update Status to "In Progress"
  • Future: When complete, update Status to "Resolved" and document completion date

Notes

Developer Note: When working on Telegram or WealthOS code, be aware of this technical debt. Don't extend the legacy pattern - if you need to add functionality to these integrations, use the integrations table pattern and accelerate this migration.

Business Note: This is internal code quality debt with no user-facing impact. Prioritize based on team capacity and upcoming integrations (WhatsApp, Signal, Slack, etc.). When adding a 3rd integration, strongly consider doing this migration FIRST to avoid three-way pattern divergence.