Data Flow Document
Data Flow Document
Project: {{PROJECT_NAME}}Drop
Version: {{VERSION}}1.0
Date: {{DATE}}2026-02-23
Author: {{AUTHOR}}Petter Graff, Senior Enterprise Architect
Status: Draft | In Review | Approved
Reviewers: {{REVIEWERS}}Alem Bašić (CEO), John (AI Director)
Classification: Public | Internal | Confidential | Restricted
Document History
| Version |
Date |
Author |
Changes |
| 0.1 |
{{DATE}}2026-02-23 |
{{AUTHOR}}Petter Graff |
Initial draft from real architecture and schema docs |
1. Data Flow Overview
System: {{SYSTEM_NAME}}Drop Payment Platform (ALAI Holding AS)
Data Owner: {{DATA_OWNER_ROLE}}Alem Bašić, CEO — [email protected]
DPO Contact: {{DPO_EMAIL}}[email protected] (DPO designation TBD — required before production launch per GDPR Art. 37)
Overview: {{DESCRIBE_WHAT_DATA_FLOWS_THROUGH_SYSTEM}}Drop processes personal, financial, and compliance data for Norwegian residents (18+) using a PSD2 pass-through model. Data enters from three surfaces: user registration (BankID OIDC), transaction initiation (web + mobile clients), and compliance webhooks (Sumsub KYC). Data is stored in 19 PostgreSQL tables, with sensitive fields (national ID, IBAN) hashed or encrypted. Data exits through the REST API (user-facing), PISP calls (payment rails), and regulatory reporting (Finanstilsynet, Okokrim).
Critical Architectural Principle: Drop never holds customer funds. bank_accounts.balance is a cached AISP read from the user's actual bank — not a Drop balance. No wallet, no top-up.
High-Level Data Flow
flowchart LR
subgraph Inputs["Data Sources / Ingestion"]
U[UsersBID["BankID —OIDC\n(Identity Web/App]+ API_IN[Externalage)"]
API]WEB["Web IMPORT[BulkApp\n(Next.js)"]
Import]MOB["Mobile WEBHOOK[Webhooks]App\n(Expo)"]
SUM["Sumsub Webhooks\n(KYC results)"]
OB["Open Banking AISP\n(Balance reads)"]
end
subgraph Processing["ProcessingDrop Layer"API Processing"]
AUTH["Auth Middleware\n(JWT verify, session check)"]
VAL[Validation"Input &Validation\n(validateName, Sanitization]sanitizeText,\nvalidateAmount, TRANS[validatePhone)"]
BIZ["Business LogicLogic\n(Fee /calc, Transformation]FX, ENRICH[Datadisclosure,\nKYC Enrichment]enforcement)"]
AUDIT["Audit + Compliance\n(audit_log, AML rules, STR)"]
end
subgraph Storage["StorageDrop Layer"Database (PostgreSQL 16)"]
DB[(PrimaryCORE["Core DB\nPostgreSQL)Domain\nusers, sessions,\ntransactions, bank_accounts,\nrecipients, merchants,\nnotifications, settings"]
CACHE[(Cache\nRedis)COMPLIANCE["Compliance Domain\naudit_log, aml_alerts,\nstr_reports, screening_results,\nconsents, data_access_requests,\ncomplaints"]
BLOB[ObjectSYSTEM["System\nexchange_rates, Storage\nS3/Blob]rate_limits,\ncards SEARCH[Search(future), Index\nElasticsearch]spending_limits DW[Data Warehouse\n{{DW_TECH}}(future)"]
end
subgraph Outputs["Data ConsumersEgress / Egress"Data Consumers"]
API_OUT["REST API]API\n(Web REPORTS[Reports+ /Mobile Analytics]clients)"]
EXPORT[DataPISP_OUT["Open Export]Banking THIRD[Third-partyPISP\n(Payment Integrations]initiation EMAIL[Emailto /user's Notifications]bank)"]
SEPA["SEPA/SWIFT\n(Remittance settlement)"]
REG["Regulatory Reporting\nFinanstilsynet + Okokrim (STR)"]
SENTRY["Sentry\n(Errors — PII masked)"]
end
UBID &--> API_IN & IMPORT & WEBHOOKAUTH --> VAL VAL--> BIZ
WEB & MOB --> TRANSAUTH
TRANSSUM --> ENRICHVAL
ENRICHOB --> DBCORE
& BLOB
DBBIZ --> CACHECORE & SEARCHCOMPLIANCE DB& SYSTEM
BIZ --> DWAUDIT
DBAUDIT --> COMPLIANCE
CORE --> API_OUT
& REPORTS & EXPORT
DWCORE --> REPORTS
ENRICHPISP_OUT --> THIRDSEPA
DBCOMPLIANCE --> EMAILREG
BIZ --> SENTRY
2. Data Sources & Ingestion
| Source |
Type |
Protocol |
Volume (est.) MVP) |
Format |
PII? |
Validation |
| BankID OIDC ID token |
Real-time (per login) |
HTTPS OIDC callback |
100-1000 logins/day |
JWT (signed) |
YES — pid, name |
JWKS signature + issuer + nonce + age >= 18 |
Web applicationapp usersuser actions |
Real-time |
HTTPS POST |
{{REQ_PER_DAY}}500-5000 req/day |
JSON |
YES — IBAN, amount |
Schema validation + validateName/validateAmount |
| Mobile app user actions |
Real-time |
HTTPS POST (Bearer) |
200-2000 req/day |
JSON |
YES |
SchemaSame +as business rulesweb |
MobileSumsub app userswebhooks |
Real-timeEvent-driven |
HTTPS POST (inbound) |
{{REQ_PER_DAY}}10-100 req/webhooks/day |
JSON |
YES — KYC result |
SchemaHMAC-SHA256 +signature business rulesverification |
{{EXTERNAL_SYSTEM}}Open APIBanking AISP |
Real-timeOn-demand + scheduled |
WebhooksHTTPS GET |
{{EVENTS_PER_DAY}}4 events/reads/account/day max |
JSON (Berlin Group) |
{{YES/NO}} | YES HMAC— signatureIBAN, + schema |
CSV bulk import |
Batch |
File upload |
{{IMPORTS_PER_DAY}} files/day |
CSV |
{{YES/NO}} |
Column mapping + row validation |
{{THIRD_PARTY_API}} |
Polling |
REST/HTTPS |
{{CALLS_PER_HOUR}}/hour |
JSON |
{{YES/NO}}balance |
Response schema validation + consent check |
Ingestion Error Handling
| Error Type |
Action |
Notification |
| BankID signature invalid |
Reject — return jwks_verification_failed 502 |
Sentry HIGH alert |
| Schema validation failure |
Reject — return 400 validation_error with errorfield details |
ReturnNo 400alert to caller(expected) |
DuplicateSumsub recordHMAC mismatch |
UpsertReject (prefer— existing)return or reject401 |
Log,Sentry returnHIGH 409alert — possible SUMSUB_SECRET_KEY rotation issue |
| Open Banking consent expired |
Reject AISP call — prompt user to re-link |
In-app notification |
PII fieldsfield containwith unexpected data |
Quarantine + alert |
Slack #{{CHANNEL}} |
Import file corruptedformat |
Reject entire+ filelog (masked) |
EmailSentry uploaderMEDIUM + error reportalert |
3.1 Ingestion Transformations (before storage)
3.2 ETL Pipeline
Drop does not have a separate data warehouse or ETL pipeline at MVP scale. All analytics queries run directly against the PostgreSQL replica (towhen Dataavailable). Warehouse)A
flowchartdata LRwarehouse subgraphis Extract["Extract"]planned PGLOG[PostgreSQLfor WALPhase / CDC]
SCHED[Scheduled SQL Export]
end
subgraph Transform["Transform3 ({{TRANSFORM_TOOL}})"]10K+ CLEAN[Data Cleaning]
JOIN[Joins & Aggregations]
DEDUP[Deduplication]
ANON[PII Anonymization]
end
subgraph Load["Load"]
DW[({{DATA_WAREHOUSE}})]
end
PGLOG --> CLEAN
SCHED --> CLEAN
CLEAN --> JOIN
JOIN --> DEDUP
DEDUP --> ANON
ANON --> DW
Pipeline schedule: {{PIPELINE_SCHEDULE}} (e.g., hourly incremental, daily full)
Latency: Source to DW within {{MAX_LATENCY}}
Tool: {{ETL_TOOL}} (e.g., dbt, Airbyte, custom)users).
4. Data Storage
| Storage System |
Technology |
Purpose |
Data Classification |
Encryption at Rest |
| Primary Database |
{{DB_TECH}}PostgreSQL {{VERSION}}16 (AWS RDS) |
TransactionalAll transactional and compliance data — 19 tables |
Restricted / Confidential |
AES-256 ({{KEY_MGMT}})RDS storage encryption, AWS-managed key) |
CacheDevelopment Database |
RedisSQLite {{VERSION}}3 (/app/data/drop.db) |
HotLocal data,dev sessionsonly — no real PII |
Internal |
AES-256OS-level (developer machine) |
Object StorageSecrets |
{{S3_COMPATIBLE}}AWS Secrets Manager |
Files,JWT_SECRET, documents,BankID mediacredentials, DB credentials, Sentry DSN |
{{CLASSIFICATION}}Critical |
SSE-S3AES-256 /(AWS SSE-KMSKMS) |
Search IndexBackups |
Elasticsearch | RDS Full-textautomated search |
Internal |
TLSbackups + at-rest encryption |
Data Warehouse |
{{DW}} |
Analytics, reporting |
Anonymized |
{{DW_ENCRYPTION}} |
Backup Storage |
{{BACKUP_TECH}}snapshots |
Disaster recovery |
Restricted |
AES-256 (RDS) |
AuditError Logs |
{{LOG_STORAGE}}Sentry |
ComplianceError /events audit(PII trailmasked) |
RestrictedInternal |
Immutable,Sentry's encryptedencryption |
| App Logs |
AWS CloudWatch |
Request/response logs (PII excluded) |
Internal |
CloudWatch encryption |
| Container images |
AWS ECR |
Docker images — no data, no secrets |
Internal |
ECR encryption at rest |
5. Data Access Patterns
5.1 Read Patterns
| Consumer |
Data Accessed |
Frequency |
Access Method |
Caching |
Web applicationapp (GET /api/auth/me) |
User profile, settingsbank accounts, total balance |
Per requestpage load |
REST API |
RedisBalance: 5minbank_accounts.balance_synced_at TTL(6h staleness) |
Web applicationapp (GET /v1/transactions) |
{{ENTITY}}Transaction list (paginated) |
Per page load |
REST API (paginated, limit 20) |
No cache — real-time from DB |
Mobile app (GET /v1/transactions) |
Transaction list |
Per page load |
REST API (paginated) |
CDNNo + Rediscache |
ReportingMobile serviceapp (GET /v1/recipients) |
AggregatedSaved metricsrecipients |
EveryPer 1hsend-money flow |
DWREST queryAPI |
MaterializedNo viewscache |
Web app (GET /v1/rates/:currency) |
Exchange rate |
Per amount-entry |
REST API |
Rate limited to 120/min — DB row read |
Admin dashboard(GET /api/admin/users) |
RawUser recordslist with KYC status |
On demand |
REST API (admin)admin-only) |
No cache |
External partner |
{{SUBSET_OF_DATA}} |
{{FREQUENCY}} |
REST API (scoped JWT) |
{{CACHING}} |
5.2 Write Patterns
| Writer |
Data Written |
Frequency |
Write Method |
Consistency |
UserAuth actionsmodule (web)BankID callback) |
CRUDusers, operationssessions, audit_log |
Per user actionlogin |
RESTAtomic APIDB transaction |
Strong (synchronous) |
BackgroundTransactions workerroute |
Aggregates,transactions, computedbank_accounts fields(balance deduct), audit_log, notifications |
Per payment |
Atomic DB transaction |
Strong |
| Sumsub webhook |
users.kyc_status, screening_results, audit_log, notifications |
Per KYC event |
Atomic DB transaction |
Strong (within Drop) |
| Rate limit middleware |
rate_limits (count + reset_at) |
Every {{INTERVAL}}rate-limited request |
Direct DB write |
Eventual (cleanup every 100 calls) |
ImportAISP processbalance sync |
Bulkbank_accounts.balance, recordsbank_accounts.balance_synced_at |
{{FREQUENCY}} | Up Batchto insert | 4x/day Strong (per batch) |
Event consumer |
Denormalized cache |
On eventaccount |
Direct DB write |
Eventual (cached value) |
6. Data Retention & Archival
| Data Category |
Retention Period |
Legal Basis |
Action at Expiry |
Automated? |
| User account data |
Duration of relationship + {{N}}5 years |
Contract (Finansavtaleloven) |
Soft delete → anonymize (nullify PII fields) |
AutomatedPlanned (— nightly job)job |
| Transaction records |
{{N}}5 years |
Legal obligation ({{REGULATION}})Hvitvaskingsloven § 22) |
Archive to cold storage (planned) |
AutomatedPlanned |
| AML alerts + STR reports |
5 years |
Legal obligation (Hvitvaskingsloven § 22) |
Retain — not deletable per AML law |
No (legal retention) |
Audit logs (audit_log) |
{{N}}5 years |
Legitimate interest (security)security + compliance) |
DeletePurge |
AutomatedPlanned |
Session tokens (sessions) |
{{N}}7 hours/days max |
Technical necessity |
Auto-expireExpired viaexpires_at TTLrows pruned on login |
Yes (Redissession TTL)cleanup on login) |
MarketingGDPR consentconsents |
Until consent withdrawn |
Consent (GDPR Art. 6(1)(a)) |
Delete within {{N}}30 days of withdrawal |
Manual + automatedplanned job |
AnalyticsKYC datascreening results |
{{N}}5 years |
Legal obligation |
Archive |
Planned |
| Notifications |
90 days |
Legitimate interest (anonymized)UX) |
Delete |
Planned |
| Rate limit counters |
60 seconds (TTL = reset_at) |
Technical necessity |
Auto-cleaned every 100 calls |
Yes (middleware cleanup) |
| Error logs (Sentry) |
90 days |
Legitimate interest |
DeleteAuto-purged by Sentry |
AutomatedYes (Sentry retention policy) |
BackupRDS filesbackups |
{{N}}30 days (prod), 7 days (staging) |
Business continuity |
Overwrite (rolling) |
Automated | Yes
(RDS
Error logs |
{{N}} days |
Legitimate interest |
Delete |
Automatedautomated) |
RetentionAML schedule job:Override: retention-policy.job.tsGDPR Art. 17 (right to erasure) is overridden by Hvitvaskingsloven § 22 — runstransaction dailyand atKYC {{TIME}}data UTCmust Archivalbe target:retained {{COLD_STORAGE_LOCATION}}5 years regardless of user erasure request. Drop implements soft delete + anonymization (nullify email, first_name, last_name, phone) while retaining financial and compliance records.
7. Data Quality Rules
7.1 Validation Rules
| Field |
Rule |
Error Action |
Severity |
emailusers.national_id_hash |
ValidSHA-256 RFChex 5322string format(64 chars) |
Reject login |
CRITICAL |
phoneusers.date_of_birth |
E.164ISO formatdate, age >= 18 years |
Reject login |
CRITICAL |
transactions.amount |
100 ≤ amount ≤ 50000 (NOK) |
Reject payment |
CRITICAL |
transactions.idempotency_key |
Unique (UNIQUE index) |
Reject duplicate, return existing |
CRITICAL |
recipients.country |
One of: RS, BA, PL, PK, TR, EU |
Reject recipient creation |
HIGH |
{{DATE_FIELD}}bank_accounts.iban |
NotValid inIBAN futureformat (application-layer check) |
Reject bank linking |
HIGH |
{{AMOUNT_FIELD}}users.email |
>=Placeholder 0format [email protected] |
RejectN/A (generated) |
CRITICALLOW |
Input text fields ({{FK_FIELD}}name, description) |
ReferencesSanitized existing(no recordHTML, max lengths per field) |
Reject | CRITICAL | with
{{TEXT_FIELD}} |
Max {{N}} characters |
Reject422 |
MEDIUM |
7.2 Data Quality Metrics
| Metric |
Target |
Current |
Alert Threshold |
Null rate on required fieldsusers.national_id_hash |
0% |
{{CURRENT}} | Any > 0.1%occurrence |
DuplicateTransaction rateidempotency violations prevented |
< 0.01%100% |
{{CURRENT}} | Any >duplicate 0.1%slip-through |
SchemaKYC webhook HMAC validation pass rate |
> 99.9% |
{{CURRENT}}100% |
< 99%100% → alert ops |
ETLAISP pipelinebalance successstaleness rate> 24h |
0% |
> 99.5% | {{CURRENT}} | of <accounts 98%→ alert |
8. PII Data Flow Mapping
8.1 PII Inventory
| PII Category |
Fields |
Storage Location |
Encrypted? |
Access Controls |
Lawful Basis |
ContactNorwegian infonational ID |
emailusers.national_id_hash |
PostgreSQL users table |
SHA-256 one-way hash |
Auth middleware + admin only |
Contract + Legal obligation |
| Full name |
users.first_name, phone, addressusers.last_name |
PrimaryPostgreSQL DB,users Email systemtable |
YesAt-rest (RDS encryption) |
Role-basedAuth middleware (userown selfdata) + admin)admin |
Contract |
IdentityDate of birth |
full_name, users.date_of_birth |
PrimaryPostgreSQL DBusers table |
Yes (field-level)At-rest |
Role-basedAuth middleware (own data) + admin |
Contract + Legal obligation (age verification) |
| Phone number |
users.phone |
PostgreSQL users table |
At-rest |
Own data + admin |
Contract |
FinancialIBAN / bank account |
{{PAYMENT_FIELD}}bank_accounts.iban, bank_accounts.account_number, recipients.bank_account |
{{PAYMENT_PROVIDER}} (tokenized)PostgreSQL |
TokenizedAt-rest |
PCIOwn scopedata only (user_id FK enforced) |
Contract |
BehavioralCached bank balance |
login_historybank_accounts.balance |
PostgreSQL |
At-rest |
Own data only |
Contract (AISP) |
| IP address |
audit_log.ip_address, click_eventsconsents.ip_address, rate_limits.key |
Analytics DBPostgreSQL |
No (anonymized)At-rest |
Admin only |
Legitimate interest (security) |
LocationKYC documents |
ip_addressNot (→stored geo)by Drop |
LogsSumsub (masked)servers |
N/ASumsub handles |
AdminSumsub dashboard only |
LegitimateLegal interest |
Device |
user_agent, device_id |
Analytics DB |
No |
Admin only |
Legitimate interestobligation |
8.2 PII Flow Diagram
flowchart TD
USER([DataNorwegian Resident\nData Subject]) -->|Provides|"BankID OIDC\n(pid, name, birthdate)"| INGESTION[IngestionDrop Layer]Auth Module]
INGESTION -->|Validates"SHA-256(pid) &= encrypts|national_id_hash\nname → first/last_name\nbirthdate from pid"| DB[(PrimaryPostgreSQL\nusers DB\table\nPII encrypted at rest)]
DB -->|Pseudonymized|"Own DW[(Dataprofile Warehouse\nNoonly\n(JWT-gated)"| directAPI_OUT["REST PII)API\n/api/auth/me"]
DB -->|Masked"national_id_hash inonly\n(never logs|raw LOGS[Logpid)"| Aggregator]AUDIT[audit_log]
DBUSER -->|Tokenized|"Document PAYMENT[Paymentupload"| Provider\nPCISUMSUB_SDK[Sumsub scope]SDK DBWidget]
SUMSUB_SDK -->|Explicit"Applicant consent|data\n+ EMAIL[Emaildocument Provider\nEmailimages"| +SUMSUB[(Sumsub nameServers\nKYC only]documents DBstored)]
SUMSUB -->|Right"kyc_status toresult\n(no erasure|raw DELETION[Anonymizationdoc Service]data)"| DELETIONDROP_WEBHOOK[Drop Webhook Handler]
DROP_WEBHOOK -->|Anonymized|"kyc_status update\nscreening_result"| DB
DB -->|Audit"GDPR trail|Art. AUDIT[Audit17 Log\nRestrictederasure\n(soft access]delete + anonymize)"| ANONYMIZE[Anonymization\nNullify: email, first_name,\nlast_name, phone\nRetain: transactions, AML (5yr)]
ANONYMIZE --> DB
DB -->|"PISP: amount + IBAN\n(user's own bank)"| PISP_OUT["Open Banking PISP\n(Neonomics → ASPSP)"]
PISP_OUT -->|"Execute transfer"| BANK[(User's Bank\nmoney always here)]
DB -.->|"STR reports\n(hvitvaskingsloven)"| REG["Okokrim / EFE\n(Regulatory)"]
style DB fill:#ffcccc
style DWSUMSUB fill:#ffffcc
style BANK fill:#ccffcc
style LOGS fill:#ffffcc
style AUDITREG fill:#ffcccc
9. Cross-Border Data Transfer
| Transfer |
From |
To |
Data Category |
Mechanism |
DPA/SCCs?DPA Signed? |
{{TRANSFER_1}}KYC applicant data |
EUNorway ({{COUNTRY}})Drop) |
USInternational ({{PROVIDER}})Sumsub) |
{{DATA_CATEGORY}}Name, DOB, document images |
Standard Contractual Clauses (SCCs) |
YesTBD — signedrequired {{DATE}}before production |
{{TRANSFER_2}}Error events |
EUNorway (Drop) |
{{COUNTRY}}USA (Sentry) |
{{DATA_CATEGORY}}Error stack traces (PII masked) |
AdequacyStandard decisionContractual Clauses (SCCs) |
Sentry DPA via ToS |
| BankID auth |
Norway (user browser) |
Norway (BankID Norge) |
OIDC tokens, pid |
Norwegian entity — no cross-border transfer |
N/A |
{{TRANSFER_3}}Neonomics AISP/PISP |
EUNorway (Drop API) |
{{COUNTRY}}Norway/EEA (Neonomics) |
{{DATA_CATEGORY}}IBAN, balance, payment data |
BindingEEA Corporateentity Rules— adequacy |
{{YES/NO}}DPA required in contract |
Third-party processors with data access:
| Processor |
Service |
Data Accessed |
DPA Signed |
Location |
{{PROCESSOR_1}}Sumsub |
{{SERVICE}}KYC/AML verification |
{{DATA}}applicantId, external user ID, KYC result (documents stored by Sumsub, not Drop) |
YesRequired |
{{LOCATION}}International |
{{PROCESSOR_2}}Sentry |
{{SERVICE}}Error tracking |
{{DATA}}Error messages (PII must be masked before capture) |
YesVia Sentry ToS DPA |
{{LOCATION}}USA (SCCs) |
| AWS |
Cloud hosting |
All Drop data (encrypted at rest) |
AWS DPA |
eu-north-1 (Stockholm) — EEA |
| Neonomics |
Open Banking aggregator |
IBAN, balance, payment details |
Required in commercial contract |
Norway / EEA |
10. Data Lineage Tracking
Lineage tool: {{LINEAGE_TOOL}}audit_log (e.g.,table Apache— Atlas,custom DataHub, custom)implementation
Coverage: PrimaryAll DBuser-triggered +data DWmutations captured
Lineage Events Captured
{
"eventType"id": "DATA_WRITE"audit_<hex16>",
"timestamp"user_id": "ISO8601",
"actor": "system/user-id"usr_abc123",
"action": "CREATEtransaction.create | UPDATEkyc.approved | DELETEsession.create | EXPORT | IMPORT",
"resource": {
"type": "{{ENTITY}}...",
"id"resource_type": "UUID"transaction },| "fields_modified":user ["{{field1}}| session | ...",
"{{field2}}resource_id": "]tx_abc123",
"sourceSystem"ip_address": "{{SOURCE}}"192.168.1.1",
"traceId"created_at": "UUID"2026-02-23T10:00:00.000Z"
}
Actions tracked in audit_log:
session.create, session.revoke, session.revoke_all
transaction.create, transaction.status_update
kyc.initiated, kyc.approved, kyc.rejected
qr_payment.create
user.delete_account, user.data_export, user.data_export_request
complaint.create
bankid.login, bankid.callback_error
11. Backup & Recovery for Data
| Storage |
Backup Method |
Frequency |
Retention |
RTO |
RPO |
Test Frequency |
PrimaryPostgreSQL DB(RDS prod) |
Continuous WALautomated archivingbackups (PITR) + daily snapshots |
Continuous / Daily |
30 days |
1h1 hour |
5min5 minutes |
Monthly |
ObjectPostgreSQL Storage(RDS staging) |
Cross-regionAutomated replicationbackups |
ContinuousDaily |
307 days |
4h2 hours |
1h24 hours |
Quarterly |
DataSQLite Warehouse(dev) |
SnapshotGit-ignored; no backup (dev-only) |
DailyN/A |
14 daysN/A |
8hRebuild from seed |
24hN/A |
QuarterlyN/A |
RedisSecrets Cache(Secrets Manager) |
RDBAWS-managed snapshotsreplication |
Every 15minContinuous |
24hIndefinite (versioned) |
15min< 5 min (create new) |
15minN/A |
MonthlyN/A |
PostgreSQL Point-in-Time Recovery:
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier drop-prod \
--target-db-instance-identifier drop-prod-restored \
--restore-time "2026-02-23T10:00:00Z"
Last backup test: {{DATE}}TBD — Result:Required {{PASS/FAIL}}before production launch
Recovery runbook: {{LINK_TO_RUNBOOK}}docs/dr-runbook.md
Approval
| Role |
Name |
Date |
Signature |
| Author |
Petter Graff |
2026-02-23 |
|
| Data Owner |
Alem Bašić (CEO) |
|
|
| DPO / Privacy |
TBD — required before production |
|
|
| Security |
|
|
|
| Tech Lead |
John (AI Director) |
|
|