Lenguaje, framework y base de datos: qué elegimos y por qué. Luego, un caso real — una app móvil + panel + backend para una cadena de gimnasios en Costa Rica, conectada a los módulos de ERP 2026 (contabilidad, POS, CRM) y a su motor de workflows.
El ecosistema que analizamos antes de decidir
Hoy todo vive en PHP / Laravel: erp2026 (el ERP multi-tenant, autoridad del motor de workflows) publica un paquete Composer que dsf3 consume; ambos sirven a las apps (Expo + CRMs) por una única API REST. La pregunta: ¿qué stack usar para algo nuevo que conviva con esto?
Laravel 12 · MySQL · 666 migraciones. ERP multi-tenant (contabilidad, RRHH, POS, CRM). Autoridad del motor de workflows (paquete Composer).
Laravel 12 · MySQL · 385 migraciones. API legal de DSF. composer require el motor + sincroniza por webhooks HMAC.
Expo RN + Web. Cliente puro — REST + Bearer + Pusher + push. Mismo contrato que el CRM Next.js.
Rápido · seguro en memoria · buena comunidad — y que cargue una UI
| Lenguaje | ⚡ Velocidad | 🛡️ Mem-safe | 👥 Comunidad | 🎨 UI | 🐘 Postgres | 🏁 Veredicto — razones |
|---|---|---|---|---|---|---|
| TypeScript | ★★★★★ | ✅ | ★★★★★ | ★★★★★ | ★★★★★ | Mismo lenguaje que tu UI → un solo tipo para pantallas + API, errores atrapados en compilación. Ecosistema más grande, ya corrés Next 16. "Suficientemente rápido" para trabajo I/O-bound. |
| Go | ★★★★★ | ✅ | ★★★★★ | ★★★★★ | ★★★★★ | Mejor velocidad-por-esfuerzo + binario único → ideal para un servicio headless. Pierde el type-sharing con la UI; lenguaje nuevo para el equipo. |
| Elixir | ★★★★★ | ✅ | ★★★★★ | ★★★★★ | ★★★★★ | Realtime imbatible (Channels puede reemplazar Pusher). Paradigma nuevo fuera de tu stack; solo si es realtime-first. |
| C# / .NET | ★★★★★ | ✅ | ★★★★★ | ★★★★★ | ★★★★★ | Baterías más parecidas a Laravel (EF Core) + muy rápido. Solo si el equipo ya sabe C#; Blazor queda fuera de tu mundo React. |
| Rust | ★★★★★ | ✅ no-GC | ★★★★★ | ★★★★★ | ★★★★★ | El más rápido, sin GC — pero curva empinada, ecosistema web delgado, sin historia de UI. Solo ante un techo de performance que no tenés. |
| PHP / Laravel | ★★★★★ | ✅ | ★★★★★ | ★★★★★ | ★★★★★ | El único que puede hospedar el motor de workflows de erp2026 en-proceso (composer require). Elegilo si el servicio debe correr ese motor. |
🐘 PG = PostgreSQL (el elefante es su mascota) · 👥 = tamaño de comunidad/ecosistema · ⚡ = velocidad · 🛡️ = seguro en memoria · 🎨 = qué tan bien sirve una UI.
Dentro de TypeScript (el lenguaje elegido) + Laravel como excepción
| Framework (lenguaje) | 🔋 Baterías | 🎨 UI | ⚡ | 👥 | 🏁 Veredicto — razones |
|---|---|---|---|---|---|
| Next.js 16 + Drizzle (TS) | ✋ Mínimas (sumás ORM/queue/auth) | ★★★★★ | ★★★★★ | ★★★★★ | Igual que tu CRM (cero framework nuevo), UI + API en un solo deploy, tipos end-to-end. |
| AdonisJS 6 (TS) | ✅✅ Estilo Laravel (ORM, migraciones, colas, auth) | ★★★★★ | ★★★★★ | ★★★★★ | El feeling de Laravel en TypeScript — el salto más fácil para tu equipo; comunidad menor es el costo. |
| NestJS (TS) | ◑ Vía módulos | solo backend → UI aparte | ★★★★★ | ★★★★★ | API empresarial estructurada; más ceremonia de la necesaria acá. |
| Hono + tRPC (TS) | ✋ Mínimas | UI aparte, tipada | ★★★★★ | ★★★★★ | Liviano, rápido, edge-ready; elegilo si es más API que UI. |
| Laravel (PHP) | ✅✅ Todo | ★★★★★ | ★★★★★ | ★★★★★ | El único que hospeda el motor de erp2026 en-proceso; elegilo si eso es requisito. |
El servicio nuevo tiene su propia DB — libre de elegir la mejor
| Motor | ⚡ Velocidad (tu carga) | 🔧 Capacidades | ⚠️ Cuidado | 🏁 Veredicto |
|---|---|---|---|---|
| 🐘 PostgreSQL | Empate en lecturas simples, más rápido en JSONB / full-text / joins / time-series | Particionado nativo · JSONB · pg_trgm · FK hacia tablas particionadas |
Necesita un connection pooler | ELEGIR Mejor en tus lecturas y para cachear payloads del ERP en JSONB; resuelve tus hacks de partición/FK/ngram. |
| 🐬 MySQL 8 | Empate en simples; algo mejor en conexiones baratas | Funciona; full-text ngram; límite de FK en particiones | Particionado más torpe, JSON re-parseado | SOLO SI el servicio es Laravel y querés paridad de esquema con el ERP. |
| 🦭 MariaDB 11 | ≈ MySQL | Sin ngram FTS, mismo límite de FK | La búsqueda se degrada | EVITAR Paridad de velocidad con pérdida de capacidad. |
El ERP corre MySQL, pero eso no condiciona tu DB: se integran por la API, no compartiendo base. JSONB es ideal para guardar/consultar los payloads de webhook del ERP que cachees localmente.
Menor riesgo · mayor velocidad · una clase entera de bugs vuelta imposible
composer require), entonces ese servicio se hace en Laravel + PostgreSQL. Fuera de eso → TypeScript.Un motor de reglas "cuando pasa X → ejecutá acciones"
El disparador. Ej: weight_goal_reached.
Filtros sobre el evento. Ej: total_kg ≥ 10000.
Qué corre: crear tarea · enviar mensaje · emit_event · llamar tu webhook.
App móvil + panel + backend, conectados a ERP 2026
El cliente tiene una cadena de gimnasios. Eso calza perfecto con el modelo multi-tenant de erp2026: la cadena = un grupo, y cada sucursal = una empresa (company). La contabilidad es por sucursal; los reportes consolidados, a nivel de grupo.
Expo / React Native — los socios registran entrenamientos, ven progreso, su membresía y notificaciones. Igual que tu expertise en appmovildsf.
Next.js — el personal gestiona socios, clases, sucursales y ve métricas. El "frontend del backend".
TypeScript (Next.js / Hono) + Drizzle — una sola API que sirve a la app y al panel, compartiendo tipos con ambos.
PostgreSQL — socios, entrenamientos, levantamientos, membresías. JSONB para cachear datos del ERP.
X-Company-ID
El backend del gimnasio nunca escribe en la base del ERP. Lee/escribe vía su API (con X-Company-ID de la sucursal) y recibe webhooks HMAC del motor.
«10.000 KG levantados → 1 mes gratis → asiento en contabilidad»
total_kg del socio en PostgreSQL.weight_goal_reached {socio_id, company_id} + firma HMAC → al host Laravel.total_kg ≥ 10000 ✓ — y dispara las acciones.POST /api/actions/grant-membership → se crea 1 mes gratis en la DB del gimnasio.socio_id+meta para no premiar dos veces.Estilo distinto al motor: llamada directa a la API REST
El POS es un caso distinto al motor de workflows. El motor es un paquete (se importa, solo en PHP); el POS — como los otros 20 módulos — es un módulo interno de erp2026, y la única vía es su API REST. Dos estilos de integración:
Eventos · delegás. Tu backend emite un evento y el motor corre las reglas (en Laravel). Lo usaste para el premio de 10.000 KG.
API REST directa · vos llamás. Tu backend hace POST .../pos/sales y el módulo hace el trabajo (IVA, inventario, contabilidad, factura).
| Dirección | Cómo | Para qué |
|---|---|---|
| 📥 Leer | GET /company/pos/products · /pos/sales (rutas ilustrativas, bajo /company/* + X-Company-ID) | Mostrar catálogo, precios y ventas en la app o el panel |
| 🧾 Crear venta | POST /company/pos/sales + Idempotency-Key | Registrar una compra (membresía, suplemento, day pass) desde la app |
| 📡 Reaccionar | webhook HMAC pos.sale.created / pos.product.updated | Actualizar tu estado y avisar a la app por Pusher |
pos.product.updatedPOST /company/pos/sales · X-Company-ID · Idempotency-Key
pos.sale.created → recibo
↑ el recibo vuelve a tu backend → marca la membresía en Postgres → la app muestra «Renovada ✅»
| Regla | Por qué |
|---|---|
| ❌ Nunca escribir la DB del POS / inventario / conta | erp2026 es dueña de la lógica (IVA, CABYS, factura) — la rompés si escribís directo |
🏷️ Scopear por X-Company-ID | Cada venta pertenece a una sucursal (empresa del grupo) |
| 🔁 Idempotencia al crear venta | Un reintento no puede cobrar / asentar dos veces |
| 🔑 Auth de servicio, no del socio | El gym backend es un servicio de confianza de la empresa (app-token + X-Company-ID); los socios no son usuarios del ERP |
POST .../pos/sales (token + X-Company-ID + idempotencia), y erp2026 hace IVA + inventario + contabilidad + factura electrónica y te devuelve un webhook con el recibo.Cada módulo: ¿paquete, API o evento?
Hay tres formas de tocar erp2026. Solo dos cosas son paquetes (y son PHP); todo lo demás se consume por la red — así que tu servicio TypeScript puede usar todo erp2026, siempre por API o eventos.
Solo PHP puede importarlo. Desde TS → delegás a un host Laravel. Solo Workflows y Gamificación.
Cualquier lenguaje. Llamás /company/* con X-Company-ID + token. La mayoría de los módulos.
Cualquier lenguaje. Pusher (realtime) + webhooks HMAC (resultados del motor / módulos).
| Capacidad de erp2026 | Se distribuye como | Tu backend TS lo usa por… | En concreto |
|---|---|---|---|
| ⚙️ Motor de Workflows | 📦 Paquete · workflows-dist | 📡 Eventos (delegás) | Emitís el evento → el motor corre en Laravel y te llama de vuelta |
| 🏆 Gamificación | 📦 Paquete · gamification-dist | 🔌 API📡 eventos | Llamás «otorgar / leer puntos»; corre en Laravel |
| 📒 Contabilidad | Módulo interno | 🔌 API REST | Asientos / balances vía /company/... (scope sucursal) |
| 🛒 Punto de Venta | Módulo interno | 🔌 API📡 webhooks | POST .../pos/sales → hace IVA / inventario / conta / factura |
| 📦 Inventario | Módulo interno | 🔌 API📡 webhooks | Stock / conteos; se mueve solo desde el POS |
| 👥 CRM | Módulo interno | 🔌 API📡 webhooks | Leads / contactos del socio |
| 🧾 Factura electrónica | Vía POS / Conta (facturero) | ↪ Indirecto | No la llamás: la dispara la venta del POS |
| 🔔 Realtime | Compartido (Pusher) | 📡 Pusher SDK | Canales privados + eventos a la app |
| 🔐 Auth | Sanctum + app-token | 🔑 Token de servicio | El backend es servicio de confianza + X-Company-ID |
Tres movimientos para conectar el gimnasio al ERP
X-Company-ID.company_id. El backend llama la API del ERP (X-Company-ID + token) y recibe webhooks HMAC; los workflows (como el premio de 10.000 KG) corren en el motor de erp2026, alcance por sucursal.