Problema

Los desarrolladores que gestionan aplicaciones Laravel con datos sensibles (por ejemplo, información médica) necesitan una infraestructura que permita firmar un Business Associate Agreement (BAA). Al mismo tiempo, la mayoría prefiere evitar la complejidad de administrar servidores, contenedores, clusters de Kubernetes o configuraciones de Redis dedicadas. El reto consiste en encontrar un servicio PaaS que:

  1. Ofrezca un entorno gestionado compatible con BAA/HIPAA.
  2. Permita ejecutar Laravel, sus colas y el programador (schedule:run) sin montar infraestructura adicional.
  3. Mantenga la carga operativa al mínimo para un desarrollador solo.

Este patrón se repite en startups de salud, clínicas pequeñas y cualquier proyecto que combine Laravel con requisitos regulatorios.

Causa

Los puntos críticos que generan fricción son:

  • Falta de servicios nativos para colas y scheduler. La mayoría de los PaaS gestionan solo la capa web; el trabajo en segundo plano queda a cargo del usuario.
  • Separación de bases de datos y almacenamiento. Cuando la base de datos está fuera del entorno gestionado, la latencia y la configuración de redes pueden romper la comunicación de colas.
  • Requisitos de BAA. No todos los planes de nube incluyen cláusulas de HIPAA; el desarrollador debe seleccionar la oferta adecuada y habilitar la encriptación en reposo y en tránsito.
  • Sobrecarga de DevOps. Configurar Docker, Kubernetes o un clúster de Redis para una sola aplicación es excesivo y propenso a errores.

Solución

Una arquitectura gestión mínima + cumplimiento BAA se logra combinando:

Componente AWS (opción 1) Azure (opción 2)
Web Elastic Beanstalk (entorno PHP) Azure App Service (Linux)
Base de datos RDS MySQL (instancia Multi‑AZ) Azure Database for MySQL
Colas Amazon SQS + Laravel queue driver or Elastic Beanstalk Worker tier Azure Queue Storage + Laravel queue driver or WebJob ejecutando queue:work
Scheduler Cron de Elastic Beanstalk (configurable vía .ebextensions) Azure WebJob con trigger de “Scheduled”
Almacenamiento estático S3 (con bucket BAA habilitado) Azure Blob Storage (con política de retención)
Certificados ACM (HTTPS) Azure Front Door / App Service TLS
  1. Crear un entorno Elastic Beanstalk (PHP 8.x). Seleccionar la versión “Single Instance” para pruebas o “Load Balanced” para producción. En la sección “Configuration” habilitar “Managed Updates” y “Enhanced Health Reporting”.
  2. Vincular RDS MySQL durante la creación del entorno. Marcar la casilla “Enable storage encryption” y “Enable IAM DB authentication”.
  3. Configurar colas con SQS: crear una cola estándar, habilitar “Server‑Side Encryption (SSE)”. En config/queue.php usar el driver sqs y proporcionar key, secret, region, queue.
  4. Desplegar un Worker tier: Elastic Beanstalk permite crear un “Worker Environment” que recibe mensajes de SQS automáticamente. En la configuración del worker, establecer el comando de proceso como php artisan queue:work --sleep=3 --tries=3.
  5. Programador: añadir un archivo .ebextensions/scheduler.config que inserta una entrada en el crontab del EC2 host. El comando será php /var/app/current/artisan schedule:run >> /dev/null 2>&1.
  6. HTTPS y BAA: solicitar un certificado ACM en la región del entorno y asociarlo al balanceador de carga. Verificar que el contrato BAA está firmado con AWS (disponible en la consola “AWS Artifact”).

Paso a paso para la opción Azure

  1. Crear un App Service (Linux, runtime PHP 8.x) y habilitar “Managed Certificate”.
  2. Base de datos: Azure Database for MySQL –‑ “Enable Azure Defender for SQL” y “Data encryption at rest”.
  3. Colas: crear una Azure Queue Storage y configurar Laravel con driver azure. Alternativamente, crear un “WebJob” (continuous) que ejecute php artisan queue:work.
  4. Scheduler: crear un “WebJob” con trigger “Scheduled” (cron expression) que ejecute php artisan schedule:run.
  5. Almacenamiento de archivos: montar un contenedor Blob como “Azure Files” y usar el driver s3 de Laravel apuntando a Blob.
  6. BAA: solicitar el “Microsoft Cloud for Healthcare” agreement y habilitar “HIPAA/HITECH compliance” en la suscripción.

Ambas rutas evitan la necesidad de gestionar Docker, Kubernetes o Redis. La única pieza que queda fuera del “managed” es la configuración inicial de la cola, pero una vez creada, el servicio la mantiene.

Cuándo aplicar esta solución

Ideal cuando:

  • La aplicación está construida con Laravel y necesita ejecutar jobs y tareas programadas.
  • El equipo es de una sola persona o pequeño y no quiere mantener servidores.
  • Se requiere cumplimiento HIPAA/BAA y la nube elegida ya ofrece acuerdos firmados.
  • La carga es moderada (pocos miles de requests/mes, jobs que no requieren procesamiento intensivo).

No recomendado si:

  • Se anticipa un crecimiento explosivo que requiera sharding de bases de datos o procesamiento masivo de colas.
  • Se necesita latencia ultra‑baja entre la web y la cola (por ejemplo, procesamiento en tiempo real).
  • La arquitectura ya depende de servicios no soportados por los PaaS (por ejemplo, Redis Cluster).

Código

# .ebextensions/scheduler.config (AWS Elastic Beanstalk)
files:
  "/etc/cron.d/laravel-schedule":
    mode: "000644"
    owner: root
    group: root
    content: |
      * * * * * ec2-user cd /var/app/current && php artisan schedule:run >> /dev/null 2>&1
container_commands:
  01_reload_cron:
    command: "service crond restart"
# appservice/webjob/queue-worker.sh (Azure Continuous WebJob)
#!/bin/bash
cd /home/site/wwwroot
while true; do
  php artisan queue:work --sleep=3 --tries=3
  sleep 5
done

Verificación

  1. Web: acceder a la URL pública y confirmar que la aplicación responde bajo HTTPS.
  2. Base de datos: ejecutar php artisan migrate:status y verificar que todas las migraciones están aplicadas.
  3. Cola: enviar un job manual (php artisan queue:push "App\\Jobs\\TestJob"), luego inspeccionar la cola en la consola AWS SQS o Azure Queue Storage para confirmar que el mensaje se consume.
  4. Scheduler: crear una tarea simple ($schedule->call(function () { Log::info('cron OK'); })->everyMinute();) y revisar los logs de la instancia o del WebJob para ver la entrada cada minuto.
  5. Compliance: en la consola de la nube, abrir la sección “Artifact” (AWS) o “Compliance Manager” (Azure) y confirmar que el BAA está activo para la cuenta y la región.

Notas adicionales

  • IAM mínimo: asignar al entorno Elastic Beanstalk un rol con permisos solo a SQS, RDS y S3. En Azure, usar Managed Identity para que el App Service acceda a Blob y Queue sin claves.
  • Rotación de credenciales: habilitar “Secrets Manager” (AWS) o “Azure Key Vault” y referenciar las variables en los archivos de configuración de Laravel (.env).
  • Logs centralizados: conectar Elastic Beanstalk a CloudWatch Logs o Azure Monitor; los logs de WebJobs aparecen automáticamente en Application Insights.
  • Backup de base de datos: habilitar snapshots automáticos (RDS) o “Geo‑redundant backup” (Azure) para cumplir con los requisitos de retención de datos de HIPAA.
  • Escalado futuro: si la carga supera el nivel de un solo nodo, simplemente cambiar el entorno a “Load Balanced” y habilitar “Auto Scaling” sin tocar la lógica de colas o scheduler.

Con esta arquitectura, un desarrollador solo puede lanzar una aplicación Laravel, cumplir con los requisitos de BAA y dedicar su tiempo a código en lugar de a la gestión de infraestructura.