Backend Development 18 min read

Design and Implementation of a Flexible Membership Rights System

This article presents a comprehensive design and implementation of a flexible membership rights system, covering business goals, a rights configuration pool, user rights acquisition and execution flows, template‑method pattern, distributed locking, and asynchronous job handling to achieve smooth product upgrades and reliable rights management.

Yang Money Pot Technology Team
Yang Money Pot Technology Team
Yang Money Pot Technology Team
Design and Implementation of a Flexible Membership Rights System

Background – Membership services are a common C‑end strategy for internet platforms, and the company aims to treat membership as a core product similar to e‑commerce PLUS or VIP memberships. Existing systems suffer from rigid product upgrades, weak user perception, and chaotic rights processing.

Business Goals – Enable rich membership product forms with smooth upgrades, provide a clear rights panel for users, and standardize the rights lifecycle and processing flow.

Design Overview – Introduce a Rights Configuration Pool to decouple rights from hard‑coded product definitions, allowing flexible composition (R1+R2+...), A/B testing, and one‑click updates. A User Rights Pool records each user’s rights after order payment, simplifying queries and inventory deductions.

Two implementation schemes were evaluated: (1) write a full permutation of right‑id, quantity, user‑id, order‑id into a rights flow table; (2) introduce a User Rights Pool where each purchase writes a record that can be decremented on use. Scheme 2 was chosen for clearer architecture and better state management.

User Rights Acquisition – Rights are fetched from the configuration pool, and the relationship Order → Product → Rights is established. Challenges include multiple join queries and inventory deduction requiring distributed locks.

// Query used count
int usedRightCount = queryUsedRightCount(userId, rightType);
int remainingRightCount = rightTotalCount - usedRightCount;
if (remainingRightCount > 0) {
    return redisLock.lockAndRun(lockPrefix + userId, () -> {
        remainingRightCount = refreshRightTotalCount(userId, rightType) - queryUsedRightCount(userId, rightType);
        if (remainingRightCount > 0) {
            doUseRight();
            return true;
        }
        return false;
    });
}
return false;

User Rights Execution – The old system had disparate flows for different rights (A, B, C). A unified template‑method pattern is introduced with an abstract BaseRightFlowService handling common steps (useRight, activateSingleRightRecord) while subclasses implement hooks such as preCheckUseRightParam and sendCoupon . A factory selects the appropriate implementation based on right type.

During rights triggering, idempotency, inventory checks, and custom validations are performed. The process locks the user‑rights record, decrements inventory, creates a rights‑use record, and logs monitoring data.

@Transactional
public Long trigger(Long userId, String triggerEventId, RightType useRightType) {
    UserRelationRightDetail detail = getCanUseRightDetail(userId, triggerEventId, useRightType);
    BaseRightFlowService service = rightFlowServiceFactory.getRightFlowService(useRightType);
    boolean canInit = commonCheck(triggerEventId, useRightType, detail) && service.preCheck(triggerEventId, useRightType, detail);
    if (!canInit) return null;
    UserRelationRight right = userRightDao.lock(detail.getId());
    if (right.getCount() > 0) {
        userRightDao.reduceCountById(right.getId());
        UserUseRightRecord record = service.init(triggerOrderId, detail);
        userUseRightRecordDao.insert(record);
        monitorService.logUseRight(userId, useRightType, useRightType.getInitStatus());
        return record.getId();
    }
    return null;
}

Rights delivery is handled asynchronously by a scheduled job that scans pending records and invokes sendUserRight . The template method in the implementation layer performs the actual third‑party interaction, updates status, and logs success or failure.

protected void doExecute(JobExecutionContext ctx) {
    List
records = userUseRightRecordDao.getByStartTimeAndStatus(LocalDateTime.now(), UserUseRightRecordStatus.AVAILABLE);
    records.forEach(r -> rightFlowServiceFactory.getRightFlowService(r.getRightId()).sendUserRight(detail, r));
}

Three deployment modes are supported: standard (full flow), business‑side execution (rights affect order pricing without actual delivery), and notification mode (third‑party notifies completion).

Summary and Outlook – The new rights system migrates 40+ rights and 30+ products to a flexible architecture, supports seamless upgrades, records detailed usage for analytics, and provides a solid foundation for future rights expansion and recommendation features.

design patternsjavabackend architecturedistributed lockmembershiprights management
Yang Money Pot Technology Team
Written by

Yang Money Pot Technology Team

Enhancing service efficiency with technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.