Система подписок (FREE/PREMIUM)
Relevant source files
The following files were used as context for generating this wiki page:
- internal/features/subscriptions/transport/http/update_subscription.go
- internal/features/users/service/update_subscription.go
- internal/core/config/config.go
- internal/features/users/model/user.go
- internal/features/tracks/service/play.go
- internal/features/playlists/service/create.go
- internal/features/favorites/service/add.go
- internal/core/middleware/middleware.go
- migrations/001_init.up.sql
Introduction
The subscription system is a core module of the Music Service designed to differentiate user access levels and enforce functional limitations based on the user's tier. The system supports two primary tiers: FREE (default) and PREMIUM. It governs access to playback, playlist creation, and the "favorites" feature by applying configurable quotas that are checked during service execution.
This system is integrated throughout the application, from the database schema and JWT authentication claims to the business logic layer where limits are enforced. Administrative users have the authority to upgrade or downgrade user accounts, allowing for monetization and access management.
Subscription Tiers and Limits
The service defines two constants for subscription types: FREE and PREMIUM. New users are assigned the FREE tier by default upon registration.
Functional Constraints
The following table summarizes the limitations applied to FREE users. PREMIUM users are exempt from these restrictions.
| Feature | Limit Type | Default Value | Source of Truth |
|---|---|---|---|
| Daily Playback | Maximum tracks played per day | 10 | FREE_DAILY_PLAY_LIMIT |
| Playlists | Maximum created playlists | 3 | FREE_PLAYLIST_LIMIT |
| Favorites | Maximum tracks in favorites | 20 | Hardcoded in Service Injection |
Sources: [internal/features/users/model/user.go:12-15], [internal/core/config/config.go:31-32], [cmd/app/main.go:120-124]
Architecture and Enforcement Logic
Data Model and Authentication
The user's subscription status is persisted in the users table and embedded into the JWT Claims during authentication. This allows the system to verify the subscription type without redundant database queries on every request.
The diagram above shows the relationship between the persistent User record and the transient JWT claims used for authorization.
Sources: [migrations/001_init.up.sql:1-10], [internal/core/middleware/middleware.go:18-24]
Limit Enforcement Workflow
Limits are enforced at the Service layer. When a user attempts an action (e.g., playing a track), the service retrieves the subscription_type from the request context and checks it against the defined limits.
Track Playback Logic (Daily Limit)
For FREE users, the system uses Redis to track the number of playbacks in a 24-hour window.
The flow demonstrates how Redis provides a performant way to manage volatile daily counters for the FREE tier.
Sources: [internal/features/tracks/service/play.go:37-77]
Playlist and Favorites Quotas
For playlists and favorites, the service performs a count query against the PostgreSQL database before allowing a new entry.
// Example: Playlist limit check
if subscriptionType == "FREE" {
count, err := s.repo.CountByUserID(ctx, p.UserID)
if count >= s.playlistLimitFREE {
return nil, ErrPlaylistLimitExceeded
}
}
Sources: [internal/features/playlists/service/create.go:13-25], [internal/features/favorites/service/add.go:12-25]
Administrative Management
Administrators can modify a user's subscription tier via a dedicated HTTP endpoint. This action updates the database and logs the administrative change.
Subscription Update API
- Endpoint:
PATCH /api/v1/admin/users/{id}/subscription - Access: Restricted to users with the
ADMINrole. - Payload:
{"subscription_type": "PREMIUM"}
This diagram illustrates the administrative flow for promoting or demoting user accounts.
Sources: [internal/features/subscriptions/transport/http/update_subscription.go:35-65], [internal/features/users/service/update_subscription.go:11-23]
Configuration Reference
Subscription-related environment variables used in internal/core/config/config.go:
| Variable | Type | Default | Description |
|---|---|---|---|
FREE_DAILY_PLAY_LIMIT | Int | 10 | Max tracks per day for FREE users. |
FREE_PLAYLIST_LIMIT | Int | 3 | Max playlists a FREE user can own. |
Sources: [internal/core/config/config.go:54-55]
Summary
The Subscription System provides a robust mechanism for tier-based access control. By leveraging Redis for high-frequency daily limits and PostgreSQL for persistent entity quotas, it ensures system scalability. Integration with JWT claims ensures that the subscription status is readily available for logic enforcement across all features, including tracks, playlists, and favorites.