At a glance#
| Number | Value | What it drives |
|---|---|---|
| ETC crossings, NH plazas | ~120 lakh a day · ~139 / s average | the switch is small; the edges are hard |
| Collection via FASTag | ~₹184 crore a day · ~₹153 a crossing | settlement netting, not throughput |
| Tags · issuers · acquirers | 11.73 crore · 40 · 12 | one shared registry, the Mapper |
| Fee plazas | ~1,150 | list fan-out; offline sites |
| Online · late window | 15 min · 3 days | who carries balance risk when late |
| Exception list refresh | diff every 10 min · full daily | staleness at the lane |
| Issuer grace · decline rule | 20 min · 60 min before read (code 176) | who pays for a stale list |
| Settlement | 3 cycles a day, RTGS · plaza paid T+1 | scheduled netting job |
Architecture#
DiagramLanes decide locally; banks settle centrally
%% title: Lanes decide locally; banks settle centrally
flowchart TD
V@{ icon: "sd:truck", label: "Vehicle with FASTag<br/>signed TID · EPC" }
RDR@{ icon: "sd:scan", label: "RFID reader<br/>dozens of reads" }
LC["Lane controller<br/>passage · signature · local list"]:::hot
PS@{ icon: "sd:server", label: "Plaza server<br/>outbox · store and forward" }
ACQ["Acquirer host<br/>fare from Mapper class"]:::core
MAP@{ icon: "sd:database", label: "NETC Mapper<br/>tags · class · exception lists" }
SW["NETC Switch<br/>acquirer to issuer"]:::core
ISS["Issuer host<br/>debit · low balance · hotlist"]:::core
NRCS@{ icon: "sd:bank", label: "NRCS<br/>3 cycles · net · disputes" }
USR@{ icon: "sd:phone", label: "Tag holder<br/>SMS · UPI top-up" }
V ==> RDR ==> LC
LC ==> PS ==> ACQ
ACQ -->|"request details"| MAP
ACQ ==>|"request pay"| SW
MAP -.->|"diff every 10 min"| PS
SW ==> ISS
SW --> NRCS
ISS -.->|"status changes"| MAP
ISS --> USR
class V client
class RDR edge
class PS service
class MAP store
class NRCS store
class USR client- The lane never waits on the network: signed tag data and a local list decide; the debit can follow hours later.
- Lists flow out, crossings flow in: issuers change status in the Mapper; acquirers push diffs to plazas; crossings go lane → plaza → acquirer → switch → issuer.
- The switch settles what it processed: issuers must honour every forwarded transaction; NRCS nets three times a day.
DiagramThe lane's decision in about a second
%% title: The lane's decision in about a second
flowchart TD
READ@{ icon: "sd:scan", label: "Passage formed<br/>one txn number" }
FMT{"Known issuer ID?"}
LIST@{ icon: "sd:file", label: "Local exception list<br/>INIT + diffs" }
SIG["Verify issuer signature<br/>over TID + EPC"]:::core
ONL{"Request details<br/>answers in budget?"}
PASS["Store crossing, then<br/>lift barrier"]:::core
OTHER["Other payment mode"]:::bad
READ ==> FMT
FMT ==>|"yes"| LIST
FMT -->|"no"| OTHER
LIST ==>|"clean"| SIG
LIST -->|"blocked"| OTHER
SIG ==>|"valid"| ONL
SIG -->|"invalid"| OTHER
ONL ==>|"active or no answer"| PASS
ONL -->|"blocked"| OTHER
class READ edge
class LIST cacheKey flows#
DiagramAn online crossing, read to SMS
%% title: An online crossing, read to SMS sequenceDiagram autonumber participant L as Lane participant A as Acquirer participant M as Mapper participant S as Switch participant I as Issuer L->>L: 31 reads · one passage · txn number L->>A: request details for tag T A->>M: get tag details M-->>A: class · active · issuer A-->>L: OK · barrier lifts A->>S: request pay · same txn number S->>I: debit request I-->>S: debited · SMS sent S-->>A: response pay OK I->>M: add T to low balance
DiagramLate and failed paths, each with a written rule
%% title: Late and failed paths, each with a written rule
sequenceDiagram
autonumber
participant P as Plaza
participant A as Acquirer
participant S as Switch
participant I as Issuer
Note over P: link down · crossings wait in the outbox
P->>A: crossings, oldest first, on reconnect
A->>A: drop duplicates · plaza, txn number, read time
A->>S: request pay
alt within 15 min
S->>I: debit · normal liability
else 15 min to 3 days
S->>I: debit · issuer may charge back if balance short
else over 3 days
S-->>A: declined
end
alt issuer unreachable
S->>I: debit advice until ACK or cut-off
S-->>A: deemed accepted
else no final answer at acquirer
Note over A: wait 60 to 180 s · check transaction before any resend
endData model#
DiagramCore entities across NPCI and the banks
%% title: Core entities across NPCI and the banks
classDiagram
class Tag {
+epc : 96 bits · issuer ID, key index, vehicle ID
+tid : chip ID from manufacturer
+signature : issuer key over TID + EPC
+vrn : string · validated on VAHAN
+vehicleClass : string · overrides AVC for fare
+status : active, low balance, hotlist, blacklist, closed
}
class Issuer {
+issuerId : 20 bits
+keys : up to 256 · certified by NPCI
}
class Plaza {
+plazaId : string
+acquirer : one bank at a time
+listVersion : last diff applied
}
class Crossing {
+txnNumber : minted in the lane
+readerTime : time
+fare : rupees · from Mapper class
+state : stored, presented, settled, declined
}
class SettlementWindow {
+cycle : one of three a day
+netByBank : one amount per bank · sums to zero
}
class Dispute {
+type : adjustment, chargeback, arbitration
+deadline : days
}
Issuer "1" --> "many" Tag : issues
Tag "1" --> "many" Crossing : charged by
Plaza "1" --> "many" Crossing : records
Crossing "many" --> "1" SettlementWindow : netted in
Crossing "1" --> "0..1" Dispute : contested by- The Mapper is the one shared index across 40 issuers, keyed by tag and by VRN; one-vehicle-one-tag is a conditional write there.
- The transaction number minted in the lane is the idempotency key at every hop through settlement.
Lifecycle#
DiagramA crossing, from read to settlement
%% title: A crossing, from read to settlement stateDiagram-v2 [*] --> READ: passage formed READ --> STORED: written to lane outbox STORED --> PRESENTED_ONTIME: at switch within 15 min STORED --> PRESENTED_LATE: 15 min to 3 days STORED --> EXPIRED: not presented in 3 days PRESENTED_ONTIME --> SETTLED: next NRCS cycle PRESENTED_LATE --> SETTLED: next NRCS cycle PRESENTED_ONTIME --> DECLINED: code 176 PRESENTED_LATE --> DECLINED: code 176 SETTLED --> DISPUTED: chargeback or adjustment DISPUTED --> SETTLED: resolved SETTLED --> [*] DECLINED --> [*] EXPIRED --> [*] class SETTLED ok class EXPIRED bad class DECLINED bad class PRESENTED_LATE queue
Decisions#
| Decision | Chose | Over | Because |
|---|---|---|---|
| Barrier decision | Local: signature + local list | Real-time issuer check | lane can't wait or trust its link |
| Tag trust | Issuer signature over TID + EPC | Online lookup only | works offline; copies fail on TID |
| List delivery | 10-min diffs + daily full list | Full list every few minutes | full list large, changes small |
| Duplicates | Txn number minted in the lane | Dedupe at the issuer only | retries harmless at every hop |
| Late crossings | Accept to 3 days, shift risk | Reject after 15 min | a fibre cut isn't a revenue loss |
| Issuer outage | Deemed accepted, issuer catches up | Decline at the switch | vehicle already through |
| One tag per vehicle | Check at the shared Mapper | Each issuer checks alone | no issuer sees the others |
When it breaks#
| Failure | What users see | Contain it with |
|---|---|---|
| Plaza link down | nothing; SMS hours later | lane outbox; 3-day window; outbox-age alerts |
| Stale list after top-up | sent to pay another way | online check first; 10-min diffs |
| Issuer down | normal crossing | debit advice; deemed accepted; catch up by cut-off |
| Cloned tag | charge at a far plaza | 120 km/h near-time rule; chargeback; compensation fund |
| Tag not read, ETC fault | passes free | 2018 gazette rule; handheld reader; replace tag |
| Wrong class in Mapper | car fare for a truck | debit adjustment; issuer fixes class |
Say it in the interview#
- "The lane decides with what it holds": signed tag data and a local list; never block a barrier on a network call.
- One number per crossing: mint the transaction number in the lane and carry it to settlement; duplicates die at each hop.
- Liability is written into time: 15 minutes, 3 days, 20 and 60 minutes say who pays for each delay.
- Lists are a cache with a price: diffs every 10 minutes, a daily full list, and an SLA that puts stale-list losses on the acquirer.
- The switch settles what it processed: issuers carry credit risk and manage it with low-balance lists; deemed acceptance covers outages.
- Settlement is a netting job: three windows a day, one amount per bank, positions sum to zero.
- Identity is the next frontier: one active tag per vehicle via the shared Mapper; accurate VRNs matter most once barriers go (MLFF).