Nền tảng Smart Office · Tech Heart (Tini Group), 2024–2025

Backend Smart Office đa tenant tích hợp kiểm soát ra vào (IoT Access Control)

Hệ thống backend trung tâm quyết định ai được phép mở cánh cửa nào — qua khóa thông minh, vân tay hoặc thẻ từ — đồng thời đảm bảo tòa nhà vẫn duy trì quy tắc đóng/mở nhất quán ngay cả khi mất kết nối mạng. Khi công ty chuyển hướng sản phẩm (pivot), toàn bộ nền tảng định danh và phân quyền này được tái sử dụng nguyên vẹn thay vì phải xây lại từ đầu.

NestJS · PostgreSQL · MongoDB · Docker

Kết quả: Phát hành sản phẩm đầu tiên trong ~2 tháng nhờ cắt gọn scope; onboard đội ngũ 9 kỹ sư với quy trình code review bắt buộc; chuyển hướng sản phẩm (pivot) mà không phải viết lại tầng định danh và phân quyền.

Bài toán thực tế

Một công ty khởi nghiệp mới thành lập cần xây dựng nền tảng backend multi-tenant quản lý tòa nhà, hệ thống cửa và nhân sự, trong đó các thiết bị đầu đọc IoT tại cửa vẫn phải tự đưa ra quyết định đóng/mở chính xác khi đường truyền mạng chập chờn.

Đội ngũ kỹ sư mới hoàn toàn; sự nhất quán trong code phải được ép bằng cấu trúc repository và công cụ tự động thay vì chờ đọc tài liệu dài.
Sản phẩm đầu tiên phải ra mắt trong vòng 2 tháng; phạm vi tính năng (scope) buộc phải cắt gọn tối đa, không được phép phình to.
Khi xoay trục (pivot) sang mảng Smart Office, hệ thống phải tận dụng lại được toàn bộ tầng định danh (identity) và quản lý đa khách hàng (multi-tenant).
Lệnh mở cửa gửi từ xa tuyệt đối không được phép kích hoạt lặp hai lần (duplicate execution) khi mạng bị timeout và ứng dụng tự động retry.

Kiến trúc hệ thống

flowchart LR
  subgraph control ["Control plane"]
    control_0["NestJS APIs"]
    control_1["Tenant and permission service"]
    control_2[("PostgreSQL transactional data")]
  end
  subgraph devices ["Devices"]
    devices_0(["Smart lock / reader"])
    devices_1["Permission snapshot on device"]
    devices_2["Idempotent door command handler"]
  end
  subgraph flex ["Flexible payloads"]
    flex_0[("MongoDB device documents")]
  end
  control_0 --> control_1
  control_1 --> control_2
  control_1 --> devices_2
  devices_2 --> devices_0
  control_1 --> devices_1
  devices_0 -->|"telemetry"| flex_0

Các quyết định kiến trúc then chốt

Server là nguồn dữ liệu chuẩn (source of truth); thiết bị lưu bản chụp quyền hạn (snapshot) có thời hạn

Mọi thay đổi phân quyền được tính toán trên server; thiết bị tại cửa chỉ lưu một bản chụp (permission snapshot) có thời hạn sử dụng để đối chiếu khi mất mạng.

Không thể thu hồi quyền ra vào kịp thời nếu thiết bị cứ tin tưởng vô thời hạn vào một danh sách phân quyền đã đồng bộ từ rất lâu trước đó.

Phương án đã loại bỏ: Lưu danh sách quyền (ACL) vĩnh viễn không có hạn sử dụng trên thiết bị — loại bỏ sau bước đánh giá an ninh (security review).

Đánh đổi: Cần quản lý thời gian sống (TTL) của bản chụp và cơ chế đồng bộ đối soát lại ngay khi thiết bị có mạng trở lại.

Lệnh điều khiển mở cửa đảm bảo tính idempotent

Mỗi yêu cầu mở cửa đều gắn kèm một mã định danh lệnh duy nhất (command ID); nhờ đó các lần gửi lại (retry) sau khi timeout đều được nhận diện là cùng một lệnh và không kích hoạt mở chốt cửa lần thứ hai.

Việc ứng dụng mobile hay thiết bị gateway tự động retry khi mạng yếu là hoàn toàn bình thường, nhưng cơ cấu chốt cửa vật lý thì không được phép nhảy hai lần.

Phương án đã loại bỏ: Gửi lệnh HTTP kiểu fire-and-forget thẳng xuống firmware thiết bị — loại bỏ ngay sau khi phát hiện lỗi cửa bị kích hoạt mở hai lần liên tiếp trong lúc kiểm thử.

Đánh đổi: Cần duy trì bộ nhớ đệm lưu lại các khóa lệnh (idempotency keys) đã xử lý trong một khoảng thời gian nhất định.

Kết hợp PostgreSQL và MongoDB theo đúng bản chất dữ liệu

Dùng PostgreSQL cho dữ liệu có tính toàn vẹn giao dịch (tenant, người dùng, cửa, phân quyền); dùng MongoDB cho các gói dữ liệu trạng thái (telemetry payload) có cấu trúc biến thiên theo từng dòng thiết bị.

Bài toán ai được phép mở cửa nào đòi hỏi ràng buộc quan hệ chặt chẽ, trong khi dữ liệu trạng thái từ nhiều hãng thiết bị phần cứng lại có cấu trúc rất khác nhau.

Phương án đã loại bỏ: Lưu toàn bộ dữ liệu vào MongoDB — loại bỏ ngay trong tuần đầu tiên khi phát sinh nhu cầu truy vấn báo cáo chéo nhiều bảng quan hệ.

Đánh đổi: Phải vận hành, sao lưu và giám sát đồng thời hai hệ quản trị cơ sở dữ liệu; ranh giới trách nhiệm của từng store phải được quy định rõ trong tầng API.

Phần tôi chịu trách nhiệm, trực tiếp viết và phân công

Chịu trách nhiệm (Own)

  • Thiết lập quy trình CI/CD, quy tắc code review, chiến lược phân nhánh (branching) và kiến trúc backend ban đầu
  • Kế hoạch kỹ thuật cho đợt pivot sản phẩm: giữ nguyên tầng tenant, authentication và ranh giới giữa các service

Trực tiếp viết (Write)

  • Hệ thống API NestJS multi-tenant và mô hình phân quyền (permission model) cho việc ra quyết định mở cửa
  • Quy trình onboard kỹ sư mới: mỗi người hoàn thành một luồng tính năng dọc hoàn chỉnh (vertical slice) ngay trong tuần đầu tiên

Phân công (Delegate)

  • Giao diện ứng dụng mobile sau khi đã chốt API contract
  • Phần tích hợp blockchain của sản phẩm đầu tiên trước khi công ty pivot

Quy mô vận hành

  • Xây dựng đội ngũ kỹ thuật ban đầu gồm 9 kỹ sư (backend, frontend và mobile)
  • Đảm nhận song song với vai trò tại InnoVerse từ tháng 08/2024 (trong đó InnoVerse là công việc chính)
  • Nền tảng Smart Office vẫn vận hành ổn định trên môi trường production tính đến lần cuối tôi bàn giao theo dõi

Ranh giới phạm vi

  • Bản phát hành sau 2 tháng đầu tiên là một nền tảng bất động sản tích hợp blockchain. Case study này trình bày kiến trúc backend kiểm soát ra vào (access control) sau khi công ty pivot sang Smart Office trên cùng nền tảng core đó.
  • Giao thức truyền thông của đầu đọc thẻ và chế độ an toàn cơ khí (fail-safe hay fail-secure khi mất điện) được cấu hình theo đặc thù từng cửa tại tòa nhà.

Các chỉ số giám sát khi vận hành

Tỷ lệ lệnh mở cửa bị gửi trùng (duplicate door commands) được hệ thống chặn lạiThời gian thiết bị mất kết nối mạng so với thời hạn còn lại của bản chụp quyền hạn (snapshot age)Nhịp độ phát hành (release cadence) hàng tuần sau khi áp dụng quy trình CI chuẩn

Nguyên tắc bất di bất dịch trong thiết kế

  • Không một lệnh điều khiển thiết bị nào được phép đi qua nếu chưa vượt qua bước kiểm tra tenant và permission trên server.
  • Khi xoay trục sản phẩm (pivot), chỉ thay thế các bảng dữ liệu nghiệp vụ, tuyệt đối không đập bỏ tầng quản lý tenant và định danh.
  • Mọi thay đổi code đều phải qua bước review bắt buộc trước khi được merge vào nhánh phát hành (release branch).

Phạm vi ứng dụng rộng hơn

  • Các đội ngũ kỹ thuật mới thành lập (greenfield) cần định hình khung kiến trúc và quy trình chuẩn trước khi chạy đua tính năng.
  • Hệ thống kiểm soát ra vào vật lý cần cơ chế vận hành dự đoán được ngay cả khi thiết bị rớt mạng.
  • Các startup cần kiến trúc nền tảng đủ tách bạch để khi đổi hướng sản phẩm vẫn giữ lại được toàn bộ tầng bảo mật và phân quyền.