Architecture Overview
RedeCasas is a hybrid static/dynamic platform. The static layer serves SEO-optimized HTML pages from R2, while the dynamic layer provides auth, billing, listings, and AI chat through Cloudflare Workers.
System Diagram
┌─────────────────────────────────────────────────────────────────────┐│ User │└─────────────────────────────────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────────┐│ Cloudflare CDN / R2 ││ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ││ │ /casas/... │ │ /jardim/... │ │/condominios/ │ Static HTML ││ └──────────────┘ └──────────────┘ └──────────────┘ ││ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ /api/* → Dev Proxy │ ││ │ (Production: Cloudflare Routes / Workers) │ ││ └─────────────────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────────────────┘ │ ┌───────────────────┼───────────────────┐ ▼ ▼ ▼┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ auth-worker │ │ billing-worker │ │ listings-worker ││ (8788) │ │ (8789) │ │ (8790) ││ │ │ │ │ ││ • Register │ │ • Checkout │ │ • Upload image ││ • Login │ │ • Portal │ │ • CRUD listings ││ • Logout │ │ • Status │ │ • Search ││ • Me │ │ • Webhook │ │ ││ • Password │ │ │ │ │└────────┬────────┘ └─────────────────┘ └─────────────────┘ │ │ ┌─────────────────┐ │ │ chat-worker │ │ │ (8787) │ │ │ │ └────────►│ • Chat / WS │ │ • Search │ │ • AI agents │ └────────┬────────┘ │ ┌────────┴────────┐ │ Shared D1 + KV │ └─────────────────┘Key Design Decisions
Why Static Pages?
Brazilian real estate SEO requires deep geographic coverage. Generating 50,000+ static pages means:
- Instant load times — no server rendering latency
- CDN cacheability — every page is just HTML in R2
- SEO score — perfect Lighthouse scores without effort
- Cost efficiency — R2 egress is cheap; no compute needed for reads
Why Workers Instead of a Monolith?
The backend is split into four independent Workers:
| Worker | Responsibility | Why Separate? |
|---|---|---|
auth-worker | Sessions, passwords, user profiles | Security boundary; can be hardened independently |
billing-worker | Stripe subscriptions | PCI-adjacent logic isolated from user data |
listings-worker | Property CRUD, R2 image uploads | Heavy I/O workload separate from chat/auth |
chat-worker | AI chat, search, WebSockets | Long-lived connections don’t block request/response workers |
All Workers share the same D1 database and KV namespace. No inter-worker HTTP calls are needed.
Why D1 + KV?
- D1 (SQLite) holds relational data: users, listings, pages, geographic data, blog posts, analytics.
- KV holds ephemeral session tokens with 7-day TTL. Instantly revocable by deleting the key.
This combination gives us SQL queryability for structured data and sub-millisecond reads for session validation.