Noureddine RAMDI / Self-hosted subscription management with local-first SQLite and multi-currency support

Created Mon, 04 May 2026 10:23:02 +0000 Modified Sat, 23 May 2026 20:41:27 +0000

huhusmang/Subscription-Management

Subscription tracking apps are everywhere, but most of them run in the cloud, collect your data, and lock you into their ecosystems. This TypeScript-based project flips that model on its head: it offers a self-hosted subscription management system that keeps your data local, supports multiple currencies with automatic exchange rate updates, and runs in a containerized environment for easy deployment. It’s a practical alternative for anyone who wants more control and privacy without sacrificing useful features like analytics and notifications.

What the subscription management system does and how it is built

This repo implements a full-stack subscription management system with a React 18 + TypeScript frontend and an Express 5 backend, all written in TypeScript for type safety and DX consistency. The backend persists data locally using SQLite, adopting a local-first architecture that keeps your subscription and expense information on your machine or server rather than relying on external databases or cloud providers.

The frontend uses Zustand for state management—a lightweight and flexible solution—and styles the UI with Tailwind CSS combined with shadcn/ui components, giving it a modern and responsive look. Internationalization is built in, supporting English and Chinese out of the box.

On the backend, Express handles HTTP requests, with session-based authentication secured by bcrypt password hashing. This means user sessions are maintained server-side, avoiding JWT complexity but requiring careful session store management in production. The backend also schedules periodic tasks using node-cron, most notably to fetch updated exchange rates from the Tianapi API, keeping multi-currency conversions accurate.

SQLite is chosen as the local data store, aligning with the local-first philosophy. This choice simplifies deployment and reduces operational overhead since SQLite is serverless and file-based. The app supports nine currencies, enabling users to track subscriptions and expenses across different monetary systems with near real-time exchange rates automatically updated.

The project has notification integrations for Telegram and email, allowing users to receive alerts about their subscriptions or other app events.

Finally, the app is containerized with Docker and offers a one-click deployment experience via Docker Compose, streamlining setup and updates.

Technical strengths and tradeoffs under the hood

The local-first SQLite architecture is the most compelling aspect here. By relying on SQLite, the app avoids the complexity and costs of running a separate database service. This is ideal for self-hosting scenarios on modest hardware or personal servers. However, SQLite’s concurrency model means write operations are serialized, which is usually acceptable for a subscription tracker with moderate write volume but could be a limitation if scaled to concurrent multi-user environments.

Using session-based authentication with bcrypt hashing is a straightforward and secure choice, emphasizing simplicity and security. The tradeoff is that sessions need to be stored and managed carefully, especially if you scale beyond a single instance or want horizontal scaling.

The scheduled exchange rate update mechanism via node-cron and the Tianapi API integration is a practical solution to keep currency conversions accurate without requiring user intervention. It also means the app can offer multi-currency expense analytics with charts rendered via Recharts, providing useful visual insights into spending patterns.

On the frontend, Zustand’s minimalist approach to state management keeps the codebase lean and easier to reason about compared to heavier frameworks like Redux. The combination of Tailwind CSS and shadcn/ui components offers a flexible styling system without the overhead of custom CSS or complex component libraries.

Docker containerization with Compose scripts enhances the developer and operator experience (DX/OX). It encapsulates all dependencies and environment configuration, making deployment consistent across environments. The provided Docker run commands and Compose setup allow users to choose between running the latest pre-built image or building locally, which is a good tradeoff between convenience and customization.

One limitation worth noting is that the app currently supports only two languages (English and Chinese), which might restrict adoption in other locales without additional i18n work. Also, the reliance on an external API (Tianapi) for exchange rates introduces a dependency that could impact functionality if the service changes or becomes unavailable.

Quick start with Docker

The project provides clear and straightforward instructions for getting started with Docker, which is the recommended deployment method.

# Clone the repository
 git clone <repository-url>
 cd subscription-management

# Configure environment variables
 cp .env.production.example .env
 # Edit .env to set port, database path, Telegram and other settings

# Start the service using the latest published image
 docker compose up -d

# Optional: pull a specific image tag
 docker pull ghcr.io/huhusmang/subscription-management:<tag>

# Optional: build the image locally
 # Edit docker-compose.yml to comment out image and uncomment build section
 docker compose build && docker compose up -d

# Alternatively, run with docker run
 docker run -d \
   --name subscription-manager \
   -e SESSION_SECRET=your_session_secret \
   -e ADMIN_USERNAME=admin \
   -e ADMIN_PASSWORD=your_admin_password \
   -e PORT=3001 \
   -v subscription-data:/app/data \
   -p 3001:3001 \
   ghcr.io/huhusmang/subscription-management:latest

After deployment, the app is accessible at http://localhost:3001 (or your configured port). The .env file allows fine-tuning of runtime parameters, including credentials, ports, and API keys.

Verdict: who is this project for?

This subscription management system is a solid choice for developers and technically inclined users who want a privacy-respecting, self-hosted alternative to popular cloud subscription trackers. Its local-first SQLite approach means it can be run on low-resource devices or private servers without the overhead of managing a full database server.

It’s particularly relevant if you need multi-currency support with automatic exchange rate updates and want expense analytics visualized simply. The Docker-based deployment lowers the barrier to entry, making it feasible to run on homelabs or VPS instances.

That said, it’s not designed for high-concurrency or multi-tenant SaaS scale. Its session-based auth and SQLite backend have inherent scalability limits. Also, non-technical users might find the setup and environment variable configuration challenging.

Overall, it’s a practical, well-architected project for those who prioritize data ownership and want a manageable, extendable subscription manager under their control.


→ GitHub Repo: huhusmang/Subscription-Management ⭐ 890 · TypeScript