---
# System prepended metadata

title: System Architecture Interview

---

# System Architecture Interview

KYC = know your customer — it is a regulatory requirement for companies to do due diligence on who their customer is and, depending on how much they are transacting, have differing levels of verification and due diligence.

## Context
Users can have up to 4 documents:

ID front
ID back
Proof of address
Selfie
If all 4 documents are verified, user is verified else user is unverified.

User can resubmit for documents that have been rejected.


## Database Design
Design tables to store all required informations

## API Endpoint Design
Design APIs for clients to query for user statuses 
Design APIs for clients to submit user documents

## Architecture Design
Design overall architecture of the service
Notes
* Assume if we use external service to verify user kyc


## Additional 
How if we want to sell the service to merchants, so they can use our service to do KYC?

Table user_kyc_status
- id (auto increment long)
- user_id (long)
- overall_status (boolean)


Table user_kyc_doc_status
- user_id (long)
- doc_type (string)
- user_kyc_doc_history_id (long)
- doc_status (boolean)

Table user_kyc_doc_history
- id (auto increment long)
- user_id (long)
- doc_location (string)
- created_at (datetime)


KYC Status API
GET /api/v1/user/me/kyc/status
Request Header:
- Authorization (jwt <token>)
- content-type
    
Response:
{
    "user_id": 123456,
    "status": "unverified",
    "submission_status": "SUBMITTED",
    "doc_status": [
        {
            "doc_type": "ID_FRONT",
            "doc_status": "VERIFIED"
        },
        {
            "doc_type": "ID_BACK",
            "doc_status": "UNVERIFIED"
        },
    ]
}
    
Response:
{
    "user_id": 123456,
    "status": "unverified",
    "submission_status": "NOT_SUBMITTED"
}
    
    
Submit KYC Doc API
POST /api/v1/user/me/kyc/submit
Request Header:
- Authorization (jwt <token>)
- content-type

Request Body:
{
    "doc_type": "ID_FRONT",
    "doc_body": "<base-64 encoded of the image>"
}
    
Response 200:
{
    "is_success": true,
    "err_code": "Err0000",
    "err_message": "OK"
}
    
Response 400:
{
    "is_success": false,
    "err_code": "Err1234",
    "err_message": "File size is too big"
}
    
Response:
{
    "user_id": 123456,
    "status": "unverified",
    "submission_status": "NOT_SUBMITTED"
}


Apps -> (API Gateway) -> (Service LB) -> Individual server Service
    
KYC service
-> external regulator
-> Database (PostgreSQL)
-> Redis cache (for storing cacheable doc statuses)


<- external regulator (webhook of the status)