Architecture
One node per RTA. Nine containers. No way in from outside.
Registry is sold white-label. Each RTA client operates a dedicated node — its own server, its own database, its own object store, its own depository credentials, its own backups and its own encryption keys. No RTA’s register touches another’s, and none of it reaches the vendor’s console.
Fleet
The control plane cannot open a connection to a node.
There is no inbound port and no public address. The control plane leaves Ed25519-signed commands in a queue that the node collects on its own schedule — addressed to one node, with a nonce and an expiry, so replays and tampering are rejected and reported.
Node identity
An Ed25519 key pair generated on the machine and never transmitted, with a signed client certificate returned at enrolment.
Outbound-only telemetry
A heartbeat every sixty seconds carrying counts and states only, filtered through an allow-list applied immediately before send.
Consent-gated support
A reverse tunnel opens only when an operator at the RTA approves it on their own node — time-boxed and recorded.
Seventy-two hour offline grace
Full local operation if the control plane is unreachable, because the answer to what happens if the vendor disappears has to be nothing.
Inside a node
Nine containers, one compose file, started by a systemd unit.
A bootstrap script takes a claim token and brings a bare Ubuntu server to a running node: preflight, packages, layout, hardening, identity, enrolment, secrets, signed stack, start, activate. Every step checks whether it has already run, so a half-finished provision is fixed by running the same command again.
| Service | Responsibility |
|---|---|
| edge (Caddy) | TLS termination, security headers, access log |
| app | The Next.js console used by RTA staff, issuer users and investors |
| worker ×2 | BENPOS ingest, reconciliation, entitlement computation, TAT escalation, IEPF clock, OCR |
| depo-connect | NSDL and CDSL SFTP pull, mailbox poll, watched drop folder |
| postgres | This RTA’s register. Data checksums on, WAL archived continuously |
| pgbouncer | Transaction pooling |
| objects (MinIO) | Scans, raw depository files, bank files, generated certificates |
| backup | Continuous WAL archive, nightly full, weekly automated restore test |
| agent | The only component that communicates with the control plane |
Ingest
Four gates, three intake paths, one parser per depository per file kind.
SFTP or FTPS pull on a schedule, IMAP mailbox poll, and a watched drop folder — because in practice all three get used. Parsers are versioned with golden-file tests. There is no shared parser that tries to be clever about both depositories.
PAN, bank account, email and mobile are hashed and masked in the ingest process. The raw values never reach the database.
- 1
Gate 1 — Shape
23 columns in order, plus the _meta sheet
- 2
Gate 2 — Control totals
SUM(qty) per depository = _meta counts
- 3
Gate 3 — Row integrity
No duplicate account keys · no negatives · pledged + locked ≤ total
- 4
Gate 4 — Continuity
Δ NSDL + Δ CDSL = 0, or a register event explains it
Deliberate choices
Each of these was a decision, and each has a reason you can argue with.
Server components for every list and dashboard
These screens are dense tables of server-owned data with no client state worth shipping. The work queue’s filter and selection is the one place a client component earns its keep.
PostgreSQL does the heavy lifting
Reconciliation is a query, not application code. Position and audit tables are partitioned by month; a mid-size issuer generates around forty thousand position rows a week and eight years of them are retained.
Jobs in the database, not an external queue
A job must be transactional with the register change it causes, and an auditor will ask what ran when. Claimed with SELECT … FOR UPDATE SKIP LOCKED.
Row-level security rather than application filtering
A query that forgets its WHERE clause still returns nothing. This is the difference between a platform you can sell to two RTAs and one you cannot.
Maker–checker as a database constraint
Policy expressed as code is auditable. Policy expressed in a user interface is not.
NUMERIC for money and quantities
Never floating point. Fractional entitlements are real — bonus rounding and splits produce them.
Raw files kept forever
When a depository disputes a figure two years later, the file you received is the argument.
Redundancy
Automatic failover is deliberately not the default.
Patroni gives automatic promotion and also split-brain risk on a two-node pair. For a share register a ten-minute human-confirmed promotion is usually the better trade. A failover that has never been rehearsed is not a failover, so the top tier carries a contractual quarterly drill.
Standard
Single node, continuous WAL archive, nightly full, offsite encrypted copy
- RPO
- ~5 min
- RTO
- 2–4 h
Resilient
DefaultPrimary plus hot standby in the same datacentre, streaming replication, manual promotion
- RPO
- ~0
- RTO
- 10–15 min
Critical
Resilient plus an asynchronous DR node in a second Indian region, quarterly failover drill
- RPO
- ~0 local, ~15 min regional
- RTO
- ~30 min regional
Integrations
Every one of these is a file or an API whose schema changes without much notice.
Each is built as a versioned adapter with golden-file tests, and the raw payload is retained.
One operational detail that will bite you
Depositories whitelist source IP addresses. Each node needs a static egress address and a process for registering it. Putting nodes behind a shared NAT loses the isolation story and tangles the whitelisting at the same time.
| Counterparty | What flows | Mechanism |
|---|---|---|
| NSDL | BENPOS, demat confirmations, remat, IDT, corporate action credits | SFTP or FTPS pull |
| CDSL | The same, with distinct file layouts | SFTP or FTPS pull |
| Exchanges | Shareholding pattern, listing certificates | Portal upload |
| MCA and IEPF Authority | IEPF-2, IEPF-4, IEPF-5 verification reports | Prescribed forms |
| SEBI SCORES | Complaint intake and action-taken reports | Portal or API |
| ODR institutions | Dispute referral and outcome | Portal |
| PAN validation | PAN status and Aadhaar linkage | API |
| KRA or CVL | KYC records for compliant holders | API |
| Penny-drop provider | Bank account validation | API |
| Bank host-to-host | Dividend payment file, UTR reconciliation, returns | SFTP, two-person release |
| E-voting agency | Register snapshot at cut-off | File |
| CAS provider | Consolidated account statement feed | File |
Want the provisioning walkthrough?
We will take a bare server to a running node on a call, and you keep the keys at the end of it.