Skip to main content

⚡ Rendimiento y velocidad

Guía para responder con datos —y no con suposiciones— a la pregunta ¿por qué una factura tarda más que antes?, sobre todo al pasar de una instalación 2025 a la 2026.

El API cronometra cada emisión y reparte su tiempo por etapa (arranque, DIAN, PDF, firma, AttachedDocument, correo, S3). La medición es interna: no aparece en ninguna pantalla, queda guardada en la tabla monitoring_slow_requests para consultarla cuando haga falta.

Al actualizar

Esta versión incluye migraciones de base de datos. Después de actualizar el código ejecute php artisan migrate. Si usa Docker, además hay que reconstruir la imagen para que quede activo OPcache (ver el punto 1).

1. Active OPcache antes que nada​

PHP 8.3 sin OPcache es más lento que PHP 7.4 con OPcache: recompila las clases del proyecto en cada petición. Es la primera causa de que el 2026 se sienta más lento que el 2025.

En Docker ya viene activo de fábrica, pero hay que reconstruir la imagen, no solo reiniciarla:

docker compose build php_api scheduling_api
docker compose up -d
docker compose exec php_api php -i | grep -E "opcache.enable|memory_consumption"

Sin Docker, agregue estos valores al php.ini y reinicie php-fpm (systemctl restart php8.3-fpm):

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2

En Windows (Laragon, solo para pruebas) además hay que descomentar zend_extension=php_opcache.dll en el php.ini de la versión 8.3 y reiniciar Apache.

Compruebe sobre php-fpm, no sobre la CLI

php -i | grep opcache ejecutado en consola siempre dirá que está apagado: en la CLI lo está a propósito. Verifíquelo dentro del contenedor del API o con un phpinfo() temporal.

2. Mida la emisión por etapas​

  1. En el .env, baje el umbral para que se registren todas las peticiones y no solo las que pasan de 3 segundos:

    MONITOR_SLOW_REQUEST_MS=0
    php artisan config:clear
  2. Emita 3 o 4 facturas reales, mejor desde su software de facturación que desde Postman, para que el tiempo incluya la red.

  3. Consulte el resultado en la base de datos:

    SELECT created_at, route, duration_ms, bootstrap_ms, query_count, query_time_ms,
    stages, top_queries
    FROM monitoring_slow_requests
    ORDER BY id DESC
    LIMIT 10;
  4. Devuelva el umbral a su valor normal (MONITOR_SLOW_REQUEST_MS=3000 o quite la línea) y vuelva a ejecutar php artisan config:clear.

Con el umbral en 0 se escribe una fila por petición

Déjelo así solo el rato que dure la medición. Las filas antiguas se borran solas a los días que indique MONITOR_RETENTION_DAYS (7 por defecto).

Cómo leer el reparto​

La columna stages trae los milisegundos de cada etapa y top_queries las consultas que más se repitieron en esa petición.

EtapaQué incluyeSi es la más alta
Arranque (bootstrap_ms)Desde que php-fpm recibe la petición hasta el primer middlewareEs entorno, no código: revise OPcache
dianEl envío completo al servicio de la DIAN, ida y vueltaNo depende del API: es la DIAN o la red del servidor
pdfPlantilla, QR, logo y escritura del PDFPlantillas con muchas líneas o un logo demasiado pesado
firma_xmlGuardar el XML firmado y comprimirloDisco lento
attacheddocumentArmar y firmar el AttachedDocumentEs otra firma XML: cientos de milisegundos son normales
correoEl envío del documento al cliente, que es sincrónicoUn SMTP lento hace esperar a quien factura
s3La subida de los archivos del documentoLa empresa tiene el almacenamiento en s3 o dual
query_time_msLa suma del tiempo de todas las consultasLa base de datos está lejos, saturada o con tablas enormes

Si la suma de las etapas es mucho menor que duration_ms, el tiempo se está yendo en el arranque y en el trabajo que no es etapa (validaciones, guardado del documento y armado de la respuesta con los base64).

Variable del .envPara qué
MONITOR_SLOW_REQUEST_MSMilisegundos a partir de los cuales se registra una petición. Por defecto 3000; 0 registra todas.
MONITOR_TRACK_QUERIESEn false se siguen registrando las peticiones lentas, pero sin el detalle de consultas.
MONITOR_RETENTION_DAYSDías que se conservan los registros. Por defecto 7.

3. Qué descartar antes de culpar al API​

  • Dónde está la base de datos. Una emisión lanza muchas consultas; lo que las convierte en segundos es que cada una viaje lejos. Con la base en otro host, en Docker Desktop o detrás de una VPN, el mismo trabajo puede costar segundos en lugar de décimas. Mírelo en query_time_ms.
  • El correo. Para comprobar cuánto pesa, emita una factura con "sendmail": false.
  • El almacenamiento S3. Con storage_mode en s3 o dual, cada documento sube sus archivos dentro de la petición. Se ve en la etapa s3.
  • El ambiente de la DIAN. Habilitación responde más lento que producción, así que no compare una instalación en habilitación contra otra en producción.
  • El límite de peticiones. El grupo api admite 60 peticiones por minuto; en facturación masiva aparecen respuestas 429 y reintentos que se viven como lentitud.
  • Las tablas de auditoría. logs guarda el cuerpo de cada llamada al API y no se purga sola.
  • Contenedores que no usa. El docker compose del 2026 levanta también el programador de tareas y el worker del extractor (con Chrome). En un VPS pequeño le quitan CPU y memoria al API: si no usa el extractor, conviene no levantar ese servicio.
  • pm.max_children de php-fpm. Si es muy bajo, las emisiones se encolan.
No use config:cache ni route:cache todavía

El proyecto aún lee algunos valores con env() en tiempo de ejecución y define rutas con closures: con la configuración cacheada esas funciones se apagarían sin avisar. Después de cambiar el .env ejecute únicamente php artisan config:clear.

4. Comparar con el API 2025​

En el 2025 no existe el módulo de monitoreo, así que la comparación se hace sobre el tiempo total que reporta su software de facturación, emitiendo el mismo tipo de documento, con el mismo número de líneas y en el mismo ambiente de la DIAN.

El detalle completo del diagnóstico, con la comparación entre ambas versiones, está en esta guía.