← ALL ARTICLES
27 Sept 2026/BLOG

Tôi xây dựng hệ thống chuyển đổi số cho doanh nghiệp

Tech Lead · Fullstack Engineer · Product Owner Domain: Enterprise Document Management Stack: Next.js · NestJS · PostgreSQL · Redis · Docker · Linux Focus: Architecture · Workflow · RBAC · Digital Signature · DevOps

Building an Enterprise Document Management System

The Context

Trong một dự án chuyển đổi số cho một đơn vị khai thác cảng quy mô lớn, tôi tham gia xây dựng một nền tảng quản lý tài liệu và quy trình nghiệp vụ dành cho môi trường doanh nghiệp.

Bài toán ban đầu nhìn khá quen thuộc:

Quản lý tài liệu.

Nhưng khi đi sâu vào nghiệp vụ, đây không còn là một hệ thống CRUD đơn thuần.

Một tài liệu có thể được tạo, phân loại, lưu trữ, phân quyền, trình ký, ký số, chuyển qua nhiều bộ phận và cuối cùng trở thành một phần của hồ sơ nghiệp vụ.

Mỗi bước đều có người thực hiện, trạng thái, quyền hạn và lịch sử.

Vì vậy, bài toán thực sự không phải là:

"Làm một hệ thống upload và download file."

Mà là:

Làm thế nào để biến một quy trình nghiệp vụ phức tạp thành một hệ thống có thể kiểm soát, truy vết và vận hành ổn định trong môi trường enterprise?

Đó là phần tôi quan tâm nhất trong dự án này.


My Role

Trong dự án, tôi tham gia ở nhiều lớp khác nhau của sản phẩm.

Không chỉ development.

1790503549953-img-9457.png

Tôi tham gia từ việc phân tích yêu cầu, trao đổi với stakeholder, thiết kế solution, phát triển backend/frontend, thiết kế permission model, triển khai infrastructure cho đến hỗ trợ production và go-live.

Vai trò của tôi có thể được nhìn ở ba góc độ:

Engineering

Thiết kế và phát triển các thành phần của hệ thống bằng:

  • Next.js
  • NestJS
  • PostgreSQL
  • Redis
  • Docker
  • Linux
  • Nginx

Product

Chuyển những yêu cầu nghiệp vụ từ phía người dùng thành:

Business Requirement
        ↓
Workflow
        ↓
System Behavior
        ↓
Technical Design
        ↓
Implementation

Đây là phần tôi nhận ra quan trọng hơn rất nhiều so với việc chỉ nhận một ticket rồi viết code.

Operations

Tôi cũng tham gia vào quá trình triển khai và vận hành hệ thống.

Một hệ thống enterprise không kết thúc ở:

git push
↓
build
↓
done

Nó chỉ thực sự bắt đầu khi người dùng sử dụng hệ thống trong môi trường thực tế.


Designing Around Business Processes

Một trong những bài toán lớn nhất là chuyển workflow ngoài đời thành workflow trong phần mềm.

Ví dụ, một tài liệu có thể trải qua:

Create
  ↓
Submit
  ↓
Review
  ↓
Approve
  ↓
Digital Signature
  ↓
Archive

Nhưng thực tế luôn có ngoại lệ.

Có thể:

  • trả lại;
  • chỉnh sửa;
  • trình ký lại;
  • thay đổi người xử lý;
  • thay đổi quyền;
  • chuyển bộ phận;
  • hoặc phát sinh một nhánh nghiệp vụ khác.

Do đó, tôi không xem workflow đơn giản là một danh sách trạng thái.

Tôi xem nó như một state transition system.

        ┌───────────┐
        │   Draft   │
        └─────┬─────┘
              ↓
        ┌───────────┐
        │ Submitted │
        └─────┬─────┘
              ↓
        ┌───────────┐
        │  Review   │
        └───┬───┬───┘
            │   │
        Reject  Approve
            │   │
            ↓   ↓
        Draft   Signing
                ↓
             Completed

Cách suy nghĩ này giúp hệ thống dễ kiểm soát hơn khi nghiệp vụ phát triển.


RBAC Is More Than Role = Permission

Một bài toán khác là phân quyền.

Ở những ứng dụng nhỏ, authorization thường bắt đầu bằng:

Admin
User
Manager

Nhưng trong enterprise system, như vậy là chưa đủ.

Quyền truy cập có thể phụ thuộc vào:

  • user;
  • role;
  • department;
  • resource;
  • folder;
  • document;
  • action;
  • scope.

Do đó, authorization cần được thiết kế như một phần của architecture thay vì rải các điều kiện permission khắp source code.

Một request không đơn giản chỉ là:

Can this user access this API?

Mà gần hơn với:

Can
  this user
  perform this action
  on this resource
  within this scope
?

Đây là một trong những bài học quan trọng của tôi khi làm enterprise software.


Document Management Is a Lifecycle Problem

Quản lý document cũng không chỉ là lưu file.

Một document có lifecycle riêng:

Metadata
   ↓
Storage
   ↓
Version
   ↓
Workflow
   ↓
Approval
   ↓
Signature
   ↓
Audit
   ↓
Archive

Điều đó khiến database design, permission model, storage architecture và workflow phải được thiết kế cùng nhau.

Một thay đổi nhỏ ở document model đôi khi có thể ảnh hưởng đến:

  • permission;
  • workflow;
  • search;
  • audit;
  • notification;
  • digital signature;
  • reporting.

Đây là lý do tôi ngày càng nhìn database và domain model từ góc độ business domain, thay vì chỉ nhìn chúng như những bảng dữ liệu.


Integrating Digital Signature

Digital signature là một ví dụ điển hình của việc business requirement trở thành technical problem.

Ở góc nhìn người dùng:

"Tôi muốn ký tài liệu."

Nhưng ở góc nhìn hệ thống, phía sau đó là:

Document
   ↓
Signature Request
   ↓
Authentication
   ↓
Signing Provider
   ↓
Signature Result
   ↓
Document Update
   ↓
Audit Trail

Hệ thống phải quan tâm đến trạng thái, lỗi, retry, tính toàn vẹn và khả năng truy vết.

Những bài toán như vậy khiến tôi nhận ra một điều:

Enterprise software thường khó ở integration và state management hơn là ở UI.


Asynchronous Processing

Một số tác vụ xử lý tài liệu không phù hợp để thực hiện trực tiếp trong HTTP request.

Ví dụ:

Upload Document
      ↓
Create Job
      ↓
Redis Queue
      ↓
Worker
      ↓
OCR / Processing
      ↓
Update Result

Thay vì bắt người dùng chờ toàn bộ quá trình xử lý hoàn thành, hệ thống có thể chuyển công việc nặng sang background processing.

Redis trở thành một phần quan trọng trong architecture để quản lý asynchronous jobs.

Điều này cũng đặt ra những bài toán khác:

  • retry;
  • failed jobs;
  • idempotency;
  • queue monitoring;
  • resource consumption;
  • worker stability.

Đây là những vấn đề rất khác với việc chỉ viết một API CRUD.


AI Is Not the Product

Trong quá trình xây dựng hệ thống, AI/OCR có thể được sử dụng để hỗ trợ xử lý tài liệu.

Nhưng tôi không xem AI là trung tâm của hệ thống.

Architecture mà tôi quan tâm hơn là:

                    ┌── OCR
                    │
Document ───────────┼── AI Processing
                    │
                    └── Metadata Extraction
                           ↓
                     Business System

AI nên là một capability có thể thay thế hoặc nâng cấp.

Domain system vẫn phải hoạt động ngay cả khi model hoặc AI provider thay đổi.

Đó là một nguyên tắc tôi muốn giữ trong những hệ thống có tích hợp AI:

Do not let the AI layer own the business domain.


Production Changes the Way You Think

Một trong những điều giá trị nhất tôi nhận được từ dự án không đến từ một framework.

Nó đến từ production.

Khi một hệ thống đang được sử dụng thật, một bug không còn là:

"Bug này fix sau."

Nó có thể trở thành:

"Người dùng đang chờ."

Trong một lần training/demo, hệ thống phát sinh vấn đề ngay trước thời điểm trình bày một chức năng.

Tôi phải chuyển từ context:

Presentation

sang:

Production debugging

Tôi truy cập server, xác định nguyên nhân, thực hiện thay đổi cần thiết và đưa hệ thống trở lại trạng thái hoạt động trong thời gian ngắn.

Trải nghiệm đó nhắc tôi rằng:

Một engineer giỏi không chỉ biết xây hệ thống. Họ phải biết hệ thống của mình đang thực sự chạy như thế nào.


Working With Stakeholders

Một phần khác của dự án mà tôi đánh giá rất cao là quá trình làm việc trực tiếp với stakeholder.

Ở những dự án enterprise, specification hiếm khi hoàn hảo ngay từ đầu.

Có những requirement chỉ thực sự rõ khi người dùng nhìn thấy software.

Vì vậy, vòng lặp thường là:

Requirement
    ↓
Prototype
    ↓
User Feedback
    ↓
Clarification
    ↓
Technical Solution
    ↓
Implementation
    ↓
Validation

Vai trò của Tech Lead trong trường hợp này không chỉ là quyết định framework hay database.

Mà còn phải làm cầu nối giữa:

Business
    ↕
Product
    ↕
Engineering
    ↕
Infrastructure

Đó là phần khiến tôi hứng thú với vai trò Tech Lead và Solution Architect.


What I Learned

Sau dự án này, cách tôi nhìn về software development thay đổi khá nhiều.

1. Enterprise software is a system, not a collection of features.

Một hệ thống lớn không thể được thiết kế bằng cách cộng dồn các feature.

Các domain phải liên kết với nhau thông qua những nguyên tắc rõ ràng.

2. Architecture starts with business constraints.

Không có architecture "tốt nhất" trong chân không.

Architecture phải trả lời được:

  • Business cần gì?
  • User cần gì?
  • Security cần gì?
  • Infrastructure chịu được gì?
  • Team có thể maintain gì?

3. Production experience changes engineering decisions.

Một solution nhìn rất đẹp trên diagram có thể trở thành vấn đề khi chạy thật.

Production buộc engineer phải quan tâm đến:

Failure
Observability
Recovery
Performance
Security
Deployment
Maintenance

4. Communication is part of engineering.

Một Tech Lead không chỉ giao tiếp với developer.

Họ phải có khả năng giải thích technical decisions cho người không viết code.

Và ngược lại, phải biến business problems thành những vấn đề kỹ thuật mà team có thể giải quyết.


Beyond CRUD

Dự án này giúp tôi bước thêm một bước trong quá trình trở thành một engineer mà tôi muốn hướng tới.

Tôi vẫn thích viết code.

Nhưng tôi không còn nhìn software engineering chỉ từ góc độ:

API
Database
UI
Deploy

Tôi bắt đầu nhìn nó như một hệ thống lớn hơn:

                Business
                   ↓
                Process
                   ↓
                Domain
                   ↓
              Architecture
              ↙          ↘
        Application    Infrastructure
              ↘          ↙
                Production
                   ↓
                  Users

Và có lẽ đây là điều quan trọng nhất tôi mang ra khỏi dự án:

Code chỉ là một phần của software engineering.

Giá trị lớn hơn nằm ở khả năng hiểu bài toán, thiết kế hệ thống, đưa nó vào production và chịu trách nhiệm khi hệ thống thực sự được sử dụng.


Confidentiality

This case study describes my role, engineering experience and general technical approach.

Due to client and project confidentiality requirements, it intentionally excludes client data, source code, credentials, internal infrastructure details, proprietary documents and other non-public information.

The technical descriptions are presented at a general level to document my professional experience without disclosing confidential project information.