Design problems
Payments & fintechMediumSDE-2 30 min

Design FASTag toll payments

Asked at
AmazonDelhiveryPaytmPhonePe

The interviewer asks

“Design the system behind FASTag electronic toll collection in India: a car with an RFID tag drives through a toll lane, the toll is deducted from the owner's linked wallet or bank account, and the barrier opens without the car stopping for long.”

What a strong answer looks like

A strong answer starts from the hard constraint at the lane: the decision to open the barrier must happen in well under a second, but the money movement crosses four parties (toll plaza, acquirer bank, the NPCI NETC switch and the issuer bank) and cannot be that fast or that reliable. So the lane decides locally using a cached tag status list (valid, blacklisted, low balance), and the debit is processed as an asynchronous, idempotent transaction through acquirer, switch and issuer, with rules for late submissions, duplicate reads and disputes. Key parts: the plaza lane controller and plaza server that keep working when the network is down, the acquirer host that validates and batches transactions, the central switch that routes by tag id to the issuer, the issuer's tag-to-account mapping and balance check, and daily settlement and reconciliation between banks. The deep dives are offline-first lane decisions, keeping status lists fresh, duplicate and wrong-class charges, and settlement.

Concepts to mention

Four-party model: plaza/acquirer, switch, issuerLocal lane decision with a cached exception listAsynchronous, idempotent debit with a unique txn_idRead deduplication window at the laneVersioned delta distribution of tag statusLiability windows for stale status and late transactionsNet settlement per cycle and three-level reconciliationDurable local queue for offline operationDisputes using camera and read evidence

1 Requirements

Functional

  • Read the vehicle's RFID tag at the lane and decide to open the barrier or not
  • Compute the toll from vehicle class, plaza, direction and return-journey or monthly pass rules
  • Debit the toll from the tag holder's linked prepaid wallet or bank account through the issuer bank
  • Notify the user by SMS or push with plaza, amount and balance
  • Maintain tag status (active, blacklisted, low balance, closed) and distribute it to all plazas
  • Settle money daily between issuer banks, acquirer banks and toll operators; handle disputes and refunds
  • Support tag issuance, recharge and vehicle registration linking (VRN to tag)

Non-functional

  • Lane decision (tag read to barrier open) under ~300 ms, without depending on a remote call
  • Lanes keep working for hours with no WAN connectivity
  • Every valid read becomes exactly one debit: no missed tolls and no double charges
  • Scale: ~1.5 crore (15M) toll transactions/day across ~1,000+ plazas; peaks of 3-4x on holiday weekends
  • Tag status changes (blacklist or recharge) reach all plazas within minutes
  • Issuer debit and user SMS within a few minutes for most transactions

Out of scope (say it out loud)

  • RFID radio hardware and antenna design
  • GNSS-based distance tolling and ANPR-only free-flow tolling (mention as future)
  • Parking and fuel payments with FASTag
  • Tag issuance KYC flow in detail

2 Estimates

Transactions~15M/day, ~175/s averagePublic NETC data shows FASTag volumes in the range of 35-40 crore transactions a month; 38 crore ÷ 30 ≈ 1.3 crore/day ≈ 150/s
Peak~700/s nationallyDaytime traffic is ~2x the daily average and long weekends add 2x more
Per plaza lane~1 vehicle every 3-6 s per laneA busy plaza with 20 lanes sees ~200-400 vehicles/minute in peak hours
Active tags~8-10 crore tagsMost registered vehicles that use highways have a tag; many crores of tags have been issued
Status list size~100-500 MB full list, small deltasIf a plaza keeps status for all tags: ~10 crore × ~4 bytes (status + id hash in a compact structure). In practice plazas keep an exception list (only non-good tags), which is far smaller
Status updates~1-5M changes/dayRecharges move tags out of low balance; debits push some into it; blacklists for KYC or closure
Storage~5 GB/day of transactions15M × ~300 bytes; kept for years for dispute and audit

3 API

EndpointWhat it does
Locallane → plaza server: TagReadtag_id (EPC/TID), lane, timestamp, AVC vehicle class, camera image ref
POST/acquirer/v1/toll-txnPlaza to acquirer: one toll transaction with unique txn_id = plaza + lane + read sequence, amount, tag_id, read_time
POST/netc/v1/debitAcquirer to NETC switch to issuer: debit request, routed by tag id to the issuer; response success / decline with reason
GET/netc/v1/exception-list?since={version}Delta of tag status changes since the plaza's last version
POST/issuer/v1/rechargeUser recharges the wallet; triggers a status change to good if it was low balance
POST/disputesUser raises a wrong or double charge with the transaction id

4 Data model

tag_registry (issuer)Postgres / core banking
tag_id (PK)vrnvehicle_classaccount_idstatusissued_atkyc_status

Issuer is the owner of tag-to-account mapping and balance. Unique vrn per active tag (one vehicle, one tag).

tag_mapper (switch)In-memory + replicated DB at the switch
tag_id prefix or tag_id → issuer_idvehicle_classstatus

Lets the switch route any tag to its issuer and lets plazas confirm the class registered for the tag.

exception_listVersioned log at switch; local SQLite/RocksDB at plaza
versiontag_idstatus (blacklist, low_balance, closed)effective_at

Only tags that are NOT good. Plazas apply deltas in order by version; full resync if they fall too far behind.

toll_transactions (plaza)Local durable queue + plaza DB
txn_id (PK)tag_idlaneread_timevehicle_classamountimage_refsync_status

Written before the barrier opens; forwarded to the acquirer when the network is up.

acquirer_txnsPostgres (partitioned by day)
txn_id (PK)plaza_idtag_idamountread_timereceived_atswitch_statusissuer_ref

Unique txn_id enforces exactly one debit per read; late arrivals flagged by received_at - read_time.

settlement_batchesPostgres + files in S3
batch_idcycleparticipantgross_debitsgross_creditsnet_positionfile_ref

Net positions per bank per settlement cycle, settled between banks; files kept for audit and disputes.

5 Architecture

CLIENTSEDGESERVICESASYNCDATAEXTERNALRFID readcheck list, log txntoll txnsdedupe by txn_iddebit requestsroute by tagdebit walletdebit alertstatus changeslist deltascycle totalsrecharge, disputesVehicle RFID tagUser app / SMSLane controller +readerPlaza server (locallist)Acquirer hostNETC switch (NPCI)Issuer bank FASTaghostException listserviceTxn queue (Kafka)Settlement & reconjobsAcquirer txn DBIssuer wallet ledgerSettlement files (S3)SMS / push provider
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

Car passes a toll lane

  1. 1The reader reads the tag's ID as the car enters the lane; an automatic vehicle classifier (AVC) and camera capture the vehicle class and number plate image.
  2. 2The lane controller checks the tag locally against the plaza's exception list: blacklisted or closed tags are refused; good tags pass.
  3. 3It computes the fare from the plaza fare table, the vehicle class registered for the tag, and any return-journey or pass entitlement held locally.
  4. 4It writes the transaction to the local durable store with txn_id = plaza_id + lane_id + sequence, then opens the barrier. Elapsed time: a few hundred ms.
  5. 5The plaza server forwards pending transactions to its acquirer bank continuously (or in small batches) over the network.
  6. 6The acquirer validates (known plaza, sane amount, not a duplicate txn_id or a repeat read of the same tag in the same lane within minutes), stores it, and sends a debit request to the NETC switch.
  7. 7The switch routes by tag to the issuer bank; the issuer debits the wallet (or account) and replies success or decline.
  8. 8The issuer sends an SMS with plaza name, amount and balance; if the balance drops below the threshold, it publishes a 'low balance' status change to the exception list.

User recharges after being blacklisted

  1. 1User recharges ₹500 via UPI in the issuer's app; the issuer credits the wallet.
  2. 2The issuer sends a status change 'good' for the tag to the switch's exception list service.
  3. 3The list service appends it with a new version; every plaza pulls deltas every minute or so and removes the tag from its local list.
  4. 4On the next trip the tag passes normally. The design must make this fast, because drivers are often recharging while standing in the lane.

7 Deep dives

Offline-first decision at the lane

A lane cannot wait for a four-party round trip over a highway network that may be slow or down. So the system splits the decision from the payment. The decision is local: the plaza holds a list of tags that must not pass (blacklisted, closed, low balance) and the fare rules, and the lane decides in milliseconds. The payment is asynchronous: the read is written to a durable local store first, then forwarded when the network allows. Use an exception list, not a full list of good tags, because most tags are good and the bad list is much smaller and changes less. This creates a risk window: a tag that went bad a few minutes ago may still pass, and its debit may later be declined. The network handles this with rules on time: the status that counts is the one at read time, so a tag blacklisted shortly before the read (inside the list propagation window) is the issuer's risk, while a stale plaza list beyond the allowed lag is the acquirer's risk. NPCI has tightened these rules over time, for example around how long before and after a read a blacklist status applies. In an interview, explaining this 'decide locally, settle later, with clear liability windows' pattern is the main signal.

Exactly one debit per crossing

Double charges are the top FASTag complaint. They come from three sources. First, multiple reads: the antenna reads the same tag many times as the car moves, and a car may stop and reverse. The lane controller collapses reads of the same tag in the same lane within a time window (say 5-10 minutes) into one transaction. Second, network retries: the plaza resends a batch after a timeout. Make every transaction carry a txn_id that is created once at the lane and never changes; the acquirer stores it with a unique constraint and the issuer deduplicates on the acquirer's reference too, so retries are safe. Third, cross-lane or cross-plaza confusion: a tag read by an adjacent lane antenna. Use antenna power tuning and cross-check with the AVC and camera; transactions where the camera plate does not match the tag's registered VRN go to an exception queue rather than being debited blindly. Also guard against missed tolls: transactions stuck at the plaza must be sent within the network's allowed window, after which they may be rejected or need a different process, so the plaza alerts when its local queue age grows. Disputes use the image and read logs to decide.

Distributing tag status to 1,000+ plazas

The exception list service keeps an append-only, versioned log of status changes: (version, tag_id, new_status, effective_at). Issuers write to it when balances cross a threshold, KYC fails or tags close. Each plaza stores the list in a local key-value store (RocksDB or SQLite) and pulls deltas since its last version every 30-60 seconds; a push channel can cut this further. If a plaza has been offline long enough that the log has been compacted past its version, it downloads a full snapshot (compressed, tens of MB) and then applies deltas. To keep it small, the full list holds only non-good tags, and low balance can be expressed as a threshold flag rather than exact balances. Consistency is eventual, so measure and alert on 'list lag per plaza', because a stale list directly costs money. A hot path matters too: when a driver recharges in the lane, the issuer can also publish the change with priority. Integrity: sign the snapshots and deltas so a compromised plaza network cannot inject a list that lets tags pass free.

Settlement and reconciliation between banks

Money does not move per transaction between banks. The switch records every approved debit and computes net positions per settlement cycle: each issuer owes the sum of its customers' tolls, each acquirer is owed the sum for its plazas, minus interchange fees. Banks settle the net amounts through their settlement accounts, and acquirers then pay toll concessionaires. Every participant receives settlement and raw transaction files for each cycle. Reconciliation runs at three levels. Plaza vs acquirer: every txn_id from plaza logs must appear in the acquirer's records (detects lost uploads). Acquirer vs switch: approved, declined and pending counts and amounts must match per cycle. Issuer vs switch: debits in the wallet ledger must match the switch's file. Breaks feed the dispute system, where users can raise wrong-class or double charges; refunds flow back as credit adjustments in a later cycle. Keep everything immutable: corrections are new adjustment records, never edits, which makes audits possible years later.

8 Trade-offs

Local decision vs online authorisation

Online authorisation (wait for the issuer's yes) gives zero credit risk but makes lanes depend on four systems and the network, and adds seconds per vehicle, which creates queues. Local decisions with an exception list keep lanes fast and resilient at the cost of a small, bounded credit risk. Hybrid: use online checks when the network is healthy and the tag is near the threshold.

Exception list vs full tag list at the plaza

A full list (every tag with status) is bigger and changes on every debit. An exception list is small and only changes when a tag goes in or out of a bad state. The trade-off is that an unknown, never-seen tag is treated as good, so newly issued tags work instantly but fake tags must be caught by the switch later.

Per-transaction push vs small batches from plazas

Sending each transaction immediately gives faster debits and SMS but more connections and overhead. Small batches (every few seconds) are efficient and handle bursts. With durable local queues both are safe; choose near-real-time with micro-batching.

9 Bottlenecks

Holiday weekend peaks

At 3-4x traffic, the switch and issuers see bursts after plazas reconnect and flush backlogs. Acquirers should rate-limit flushes and the switch should apply per-issuer backpressure; a queue (Kafka) between acquirer intake and switch calls absorbs bursts without losing transactions.

Low-balance churn

Many tags hover around the threshold, flipping in and out of the list with every debit and recharge. This inflates deltas. Use hysteresis (go bad below ₹X, go good above ₹X + margin) and encourage auto-recharge to reduce churn.

10 Failure handling

Plaza loses network

Lanes keep working using the last list and local fare rules; transactions queue locally on durable storage (with a UPS). On reconnect, the plaza uploads in order, deduped by txn_id. Alerts fire if the list or the queue is older than the allowed window.

Issuer bank down

The switch cannot get debit approvals; transactions stay pending and are retried with the same reference until the issuer returns. Lanes are unaffected. Settlement for that issuer happens in a later cycle.

Tag reader or AVC fails in a lane

The lane falls back to manual handling: the operator scans the tag with a handheld reader or reads the number plate, and the transaction uses the same flow with a flag. Highway toll rules treat a working, funded tag that the plaza fails to read differently from a vehicle with no valid tag (which pays a higher fee), so the system must record why a read failed, for audit and disputes.

11 What impresses

  • Separating the barrier decision (local, fast) from the money movement (async, multi-party)
  • Using an exception list instead of a full list, and explaining why
  • Naming all three causes of double charges and a fix for each
  • Talking about liability windows and list lag as a measured metric
  • Hysteresis on the low-balance threshold to reduce churn
  • Mentioning that the next step is free-flow tolling with ANPR and GNSS, which removes the barrier but keeps the same back end

12 Mistakes

  • Making the lane wait for a synchronous issuer debit
  • Ignoring offline operation at plazas
  • Creating a new transaction id on retry, causing double debits
  • Assuming banks move money per transaction instead of net settlement
  • Forgetting the vehicle class check and wrong-class charges
  • No reconciliation or dispute path

13 Follow-ups

Q1How would you design multi-lane free flow tolling with no barriers?
Q2How do you handle a vehicle whose tag class does not match the camera classification?
Q3How would you implement return-journey discounts within 24 hours?
Q4What if a plaza operator tries to inject fake transactions?
Q5How would you support monthly passes for local residents?
Q6How do you make sure the exception list update is fast when a driver recharges in the lane?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free