Bỏ qua nội dung

Tech Stack chính thức

1. Stack bắt buộc cho MVP

LayerCông nghệPhiên bảnGhi chú ràng buộc
Database corePostgreSQL15.xBẮT BUỘC. Không thay thế bằng MySQL/MongoDB.
GeospatialPostGIS3.3+Extension trong cùng DB.
Vector searchpgvector0.5+Extension. MVP dùng pgvector, không setup riêng vector DB.
Cache / QueueRedis7.xCache + BullMQ + rate limit + session blacklist.
Object storageMinIO hoặc S3-compatibleLưu ảnh, file pháp lý, raw HTML lớn.
Backend APIJava Spring Boot3.x (Java 21)ORM: JPA/Hibernate; migration: Flyway.
AI ServiceFastAPI (Python)3.11+REST internal, không expose ra public.
WorkerBullMQ (Node) / Celery (Python)Tùy ngôn ngữ worker (data-worker).
Search nâng caoOpenSearch2.xPHASE 2. MVP dùng PostgreSQL FTS.
ContainerDocker + Docker ComposeProduction: Kubernetes (sau MVP).
CI/CDGitHub Actions / GitLab CIPipeline test → build → deploy staging.
ObservabilityOpenTelemetry + Grafana + LokiTrace, metric, log tập trung.

2. Lý do chọn PostgreSQL làm core

  • Hỗ trợ relational + JSONB + geospatial (PostGIS) + vector (pgvector) trong cùng 1 DB → giảm complexity.
  • Transaction ACID đầy đủ — bắt buộc cho dữ liệu BĐS (sai 1 record giá có thể gây thiệt hại tỷ đồng).
  • Hệ sinh thái migration tool trưởng thành (Flyway, Alembic cho Python).
  • Có thể scale read qua replica, scale write qua partition trước khi cần shard.

3. Naming convention bắt buộc

Đối tượngConventionVí dụ đúngVí dụ sai
Bảng DBsnake_case, số nhiềulistings, contact_property_relationsListing, contactPropertyRelation
Cột DBsnake_casecreated_at, source_actor_typecreatedAt, sourceActorType
Khóa chínhid (UUID v4)id UUID PK DEFAULT gen_random_uuid()listing_id, ListingID
Khóa ngoại{table_singular}_idproperty_id, source_idpropertyFK, propertyRef
Indexidx_{table}_{cols}idx_listings_phone, idx_properties_geolistings_phone_index
Enum type{table}_{col}listing_status, property_typeListingStatusEnum
API endpointkebab-case, plural noun/api/v1/listings, /api/v1/market/price-trends/api/v1/getListing
Class JavaPascalCaseListingService, PropertyControllerlisting_service
Package Javalowercase, theo modulecom.vnexus.listings.serviceListingsService (tên file lẫn case)
Class TS (FE)PascalCaseListingCard, PropertySearchFormlisting_card
File TS (FE)kebab-caselisting-card.tsx, property-search.tsListingCard.tsx

4. Service boundary & repo layout

Cấu trúc monorepo đề xuất

vnexus/
├── backend-api/ (Spring Boot modular monolith)
│ └── src/main/java/com/vnexus/
│ ├── modules/
│ │ ├── auth/ (login, register, JWT, refresh)
│ │ ├── users/
│ │ ├── organizations/ (sàn, broker agency, RBAC)
│ │ ├── listings/ (CRUD listing, search)
│ │ ├── properties/ (CRUD property, merge, valuation)
│ │ ├── contacts/ (chủ nhà, môi giới đã nhận diện)
│ │ ├── leads/ (CRM khách mua/thuê)
│ │ ├── market/ (analytics, snapshot, trend)
│ │ ├── notifications/ (alert, email, push)
│ │ ├── admin/ (kiểm duyệt, data review)
│ │ └── aigateway/ (proxy gọi sang ai-service)
│ ├── common/
│ │ ├── config/ security/ exception/ util/
│ ├── persistence/
│ │ ├── entity/ repository/ flyway/
│ └── jobs/
│ ├── scheduler/ queue/ (Redis / BullMQ consumer nếu chạy trong JVM)
├── ai-service/ (FastAPI Python)
│ └── app/
│ ├── api/
│ │ ├── classify.py deduplicate.py valuation.py
│ │ ├── embedding.py semantic_search.py
│ ├── services/
│ ├── models/ (loaded ML models)
│ ├── schemas/ (Pydantic request/response)
│ └── utils/
├── data-worker/ (Crawl + ingest + normalize)
│ └── workers/
│ ├── crawlers/ (1 file/source)
│ ├── parsers/
│ ├── normalizers/
│ └── schedulers/
├── infra/
│ ├── docker/ k8s/ terraform/
└── docs/
├── adr/ (Architecture Decision Records)
├── api/ (OpenAPI generated)
└── runbooks/