Omar Ashraf Mohammed — home
INTERNSHIP CASE STUDYSYSTEMS / BACKEND2026

Orange Promotional Gift Fulfilment

A production-style promotional fulfilment engine designed to grant a gift exactly once under concurrent requests.

Role
Backend architecture and implementation
Status
Internship deliverable — non-production data
Stack
Java 21, Spring Boot, PostgreSQL
Fiveconcurrent calls in the exactly-once test

The integration test issues five simultaneous fulfilment requests for one eligible user and asserts exactly one grant, with the rest returning a consistent replay.

CODE-VERIFIEDGiftFulfillmentIntegrationTest.java

Overview

A promotional campaign gives eligible subscribers a gift — mobile credit, in this case — subject to frequency caps. The engineering problem is not the giving. It is that mobile networks retry, users double-tap, and clients time out and resubmit, so the same request arrives several times at once, and the system has to grant exactly one gift anyway.

Built during an internship at Orange Egypt as a production-style design, running against synthetic campaign data.

Problem

Eligibility and fulfilment must agree under concurrency. It is easy to write a system where GET /eligibility says yes, and then two simultaneous POST /fulfil calls both read "not yet redeemed", both pass the cap check, and both grant. The gap between check and write is where the money leaks.

My role

Backend architecture and implementation.

Data model

Campaigns, gifts by segment, segment assignments, cap rules, idempotency records, and an immutable redemption ledger. The ledger is append-only by design: a redemption is a fact that happened, not a row to be mutated. Uniqueness constraints at the schema level make the "exactly once" property a database invariant rather than an application convention.

API surface

Four endpoints: eligibility preview, transactional fulfilment, segment creation, and segment assignment.

Eligibility is a preview, and is named that way deliberately. It answers "would this succeed right now", which is a different and weaker statement than "this will succeed". Only fulfilment is authoritative.

Exactly-once design

Four mechanisms, in order:

  1. Request key. The caller supplies an idempotency key. A repeat of a completed request short-circuits to a fast replay path and returns the original outcome, without touching the ledger.
  2. Advisory transaction lock. Before doing anything that matters, the transaction takes a PostgreSQL advisory lock scoped to the user and campaign. Competing requests serialise here rather than racing.
  3. Re-check after acquiring the lock. This is the step people skip. Passing the idempotency check before waiting on a lock proves nothing, because the request that was ahead in the queue may have completed in the meantime. The check is repeated once the lock is held.
  4. Immutable ledger with schema-level uniqueness. If all three previous layers somehow failed, the database still refuses the duplicate.

Layers 1–3 are for correctness under normal contention. Layer 4 is for being wrong about layers 1–3.

Cap rules as data

Cap rules are rows, not code: X redemptions per Y days, attached to a gift. The demo campaign uses one-per-day for the first segment, and one-every-three-days and at most two-per-week for the second — both of which must pass.

Making this data-driven means a new segment or a changed frequency cap ships as a configuration change rather than a redeploy. On a promotional campaign, where rules change mid-flight in response to uptake, that is the difference between a marketing decision taking minutes and taking a release cycle.

Failure handling

  • Repeated identical request: fast replay, original outcome, no new ledger entry
  • Simultaneous competing requests: serialised on the advisory lock, one wins, the rest replay
  • Cap boundary: denied with a reason code rather than a generic failure, so the caller can tell the user why
  • Provider outcome: the fulfilment provider is behind an interface, so its side effects are separable from the ledger write

Test design

GiftFulfillmentIntegrationTest issues five simultaneous fulfilment calls for one eligible user and asserts exactly one grant with consistent replay for the rest, and separately exercises the cap boundary.

Concurrency bugs do not show up in single-threaded tests, so the test harness has to actually contend. Firing five real simultaneous requests at one user is the smallest setup that would catch a missing lock or a check-then-write gap.

Security and privacy

The seed data is synthetic: MSISDNs 201000000001 through 201000000003, a fictional WORLDCUP_2026 campaign, and gifts of 20 and 50 EGP.

Scope

The advisory-lock approach coordinates within a single PostgreSQL instance, which is the right scope for one campaign engine and the reason the design stays this simple. The fulfilment provider sits behind an interface, so its side effects are cleanly separable from the ledger write.

Where I would take this next

  • An outbox with provider-side idempotency, so the ledger and the external side effect commit as one story even when the provider call and the transaction disagree.
  • A retained load-test artifact, turning the concurrency design into a measured throughput and latency profile.
  • Metrics on lock wait time and replay rate — the two numbers that would tell an operator how much contention the campaign is actually producing.
  • Flyway or Liquibase for versioned schema migrations.

Constraints

  • A retry storm must not grant two gifts
  • Eligibility and fulfilment must never disagree
  • Campaign rules change often, so they cannot be compiled in
  • The redemption record has to be auditable after the fact

Artifacts

Notes on evidence

  • A production-style engineering demo built during an internship against synthetic data.

Related work