← Projects

Backend Systems

Designing Reliable Reward and Debit-Card Workflows for an Education Platform

A Django REST Framework case study focused on transactional consistency, concurrency control, and external card-provider workflows.

Role
Backend engineering across reward, account, and operational services.
Context
Electus Education Global / LHI
Period
July 2025 - June 2026
PythonDjango REST FrameworkPostgreSQLRedisCeleryElasticsearchREST APIs
Architecture Concept

A Django REST Framework case study focused on transactional consistency, concurrency control, and external card-provider workflows.

Reward Ledger
Disbursement Service
Transactional Lock
Card Provider API
Load Transaction

Overview

I worked on an education platform for Electus Education Global / LHI, including backend services related to learner rewards and debit-card workflows.

The system included services such as learner, account, and organization administration domains. The public case study intentionally keeps internal implementation details generalized.

Business Context

Reward and card-loading workflows behave like financial-style systems even when they are part of an education platform. They require careful state transitions, auditability, provider integration, and protection against duplicate processing.

Problem

The platform needed workflows that could determine eligible rewards, enforce weekly or biweekly payment schedules, aggregate appropriate ledger entries, attempt card loads through an external provider, and update transaction state without concurrent workers processing the same records at the same time.

The domain included concepts such as card programs, cards, reward ledgers, card-load transactions, card order logs, balance audits, and cron-job logs.

My Role

I contributed Python backend engineering using Django REST Framework, PostgreSQL, Redis, Celery, Elasticsearch, REST APIs, background processing, and transactional database workflows.

System Architecture

Reward workflows connected learner reward records to a disbursement service, database transaction protection, external card-provider operations, load transactions, and operational audit logs.

Balance synchronization followed a separate background path for active cards: fetch provider balance, synchronize local state, and record relevant audit information.

Technical Challenges

The central challenge was consistency under concurrency. Multiple workers or requests must not claim the same reward ledger entries or submit duplicate financial-style load operations.

Failed external operations also needed controlled retry behavior. A retry should be deliberate, auditable, and aware of transaction state.

Engineering Decisions

Critical reward processing used transaction protection concepts such as transaction.atomic() and select_for_update().

The purpose was to keep related updates inside a transactional boundary and prevent concurrent workers or requests from processing the same reward records simultaneously.

The workflow treated card-load state explicitly with statuses such as pending, success, and failed. Reward ledger state could move from pending to claimed only when appropriate.

Implementation

The implementation combined DRF APIs, service-layer workflow logic, PostgreSQL transactions, Celery background processing, Redis-supported operations, and operational models for logs and audits.

External card-provider operations were modeled around concepts such as authentication, card ordering, card loading, and balance retrieval. Private endpoint URLs and production values are intentionally not published.

Reliability & Failure Handling

The system favored transactional safeguards, idempotency, and controlled retries. It does not claim perfect exactly-once delivery. Instead, the design reduces duplicate processing risk and keeps failed operations inspectable.

Security

Card and reward workflows require careful access control, sensitive-data handling, and auditability. This case study does not publish sensitive values such as card numbers, provider identifiers, credentials, or private endpoints.

Trade-offs

Locking records with select_for_update() improves consistency but must be used carefully to avoid excessive contention. The design balances correctness for financial-style records with background processing throughput.

Outcome

The platform gained clearer reward disbursement, card-load, balance-sync, audit, and retry workflows built around Django REST Framework and transactional backend design.

What I Learned

Reliable reward systems depend on explicit state, careful database boundaries, and audit logs that help operators understand what happened after a provider call succeeds, fails, or returns an ambiguous result.