Ir al contenido principal
Estrategia de datos

Una guía para desarrolladores sobre cómo escalar Databricks Apps

Cómo mantener tu aplicación rápida y confiable a medida que crece el uso

por Bruno Tafur y Tushar Madan

  • Escalar aplicaciones en Databricks empieza antes de escribir código: define qué tan rápido debe responder la aplicación y a cuánt usuarios debe dar soporte en los momentos de mayor tráfico, y luego envía las tareas pesadas al servicio adecuado. El cómputo de la aplicación muestra la interfaz de usuario y coordina las llamadas.
  • El código que escala mantiene la aplicación fluida mientras espera respuestas de los servicios, usa caché por usuario y asegura que el estado se pueda recuperar. El estado temporal se puede reconstruir; el estado persistente se guarda en tablas de Lakebase o Unity Catalog para que cualquier instancia pueda recuperar una sesión.
  • Usa pruebas de carga y telemetría para elegir el tamaño, el número de trabajadores y la cantidad de instancias. Calcula las conexiones necesarias en Lakebase y añade recursos de cómputo para cumplir con la demanda medida y los objetivos de disponibilidad.

Enhorabuena, has creado una app en Databricks Apps y ha pasado de tener un par de usuarios a cientos o miles en toda tu organización. Tus usuarios quieren que responda rápido y se mantenga activa. Y es probable que a tu jefe no le haga mucha gracia tener que pagar por un recurso de cómputo XLarge en una pila de instancias.

¿Cómo se crea una aplicación que funcione rápido, se mantenga activa y gestione una demanda creciente? La respuesta intuitiva es más recursos de cómputo, pero eso solo ayuda una vez que sabes dónde pasan el tiempo las solicitudes y si la aplicación está diseñada para escalar: su marco de trabajo, código asíncrono y la capacidad de ejecutarse en varias instancias, para que la plataforma pueda escalarla vertical u horizontalmente con facilidad.

En esta guía, veremos cómo escalar Databricks Apps en cuatro etapas: diseño; desarrollo; prueba y despliegue; y operación (Figura 1). 

El foco de esta guía es principalmente el rendimiento de la aplicación y su resiliencia a escala; no cubre la automatización del despliegue ni la optimización del rendimiento y el escalado de otros servicios de Databricks que puedan interactuar con la app.

image1.png

Figura 1: Cuatro etapas para escalar una Databricks App.

Las buenas decisiones de escalado empiezan antes de escribir cualquier código: acuerda lo que los usuarios necesitan de la app, decide dónde se ejecutará el trabajo y dónde residirán los datos.

Empieza con los objetivos: pico de usuarios y latencia

Antes de elegir una arquitectura, ayuda determinar cuánta carga debe soportar la app y cómo es una buena experiencia. Sugerimos acordar dos objetivos principales:

  • Rendimiento: ¿con qué rapidez deben responder las acciones clave? Recomendamos objetivos de latencia de extremo a extremo basados en un percentil, como p95, que captura las experiencias más lentas que un promedio no mostrará. Incluye el renderizado de la interfaz de usuario y trata los arranques en frío por separado. Para respuestas de IA en streaming, el tiempo hasta el primer token también importa.
  • Escalabilidad: ¿cuántos usuarios están activos en el pico, con qué frecuencia la usan y qué crecimiento debe admitir la app? Los períodos de gran actividad, como el fin de mes, forman parte de esta estimación porque esa es la carga que la app debe soportar dentro de sus objetivos de latencia y tasa de errores.

Junto con esto, decide qué trabajo debe sobrevivir a un reinicio y comprueba que las dependencias críticas puedan soportarlo. Esto determina cómo divides el estado y cuántas instancias ejecutas.

A continuación, esboza algunas rutas de usuario, como abrir un panel o enviar una pregunta. Para cada acción, anota los servicios a los que llama, aproximadamente cuántas llamadas realiza y cuáles dependen unas de otras, qué tan rápido debe terminar y qué tan obsoletos pueden estar los datos en caché. Estas suposiciones dan forma a la arquitectura y a los primeros objetivos de prueba. Una vez que se ejecuta un prototipo, puedes medir las llamadas reales y revisarlas.

Supongamos que un minorista ofrece a sus 2000 gerentes de tienda una app para verificar el inventario, respaldada por Lakebase. Durante la hora más concurrida del Black Friday, 200 de ellos la están usando a la vez. Si cada uno realiza dos verificaciones de stock por minuto en promedio, son 400 verificaciones por minuto. Si cada verificación ejecuta tres declaraciones SQL contra Lakebase, espera 1200 declaraciones por minuto, o 20 por segundo en promedio durante esa hora.

Esto estima la tasa de consultas, no la concurrencia. Prueba los picos y el crecimiento, valida con el uso en vivo y presupuesta las conexiones por separado (consulta "Presupuesta las conexiones a Lakebase").

Diseño: planifica la arquitectura

Mantén el cómputo de la app para servir a la app

El cómputo de la app está ahí para servir a la interfaz de usuario y coordinar las llamadas, no para hacer el trabajo pesado. Recomendamos enviar cada tipo de trabajo al servicio creado para él (Figura 2). Para llamadas de larga duración, ejecuta el trabajo en segundo plano, por ejemplo como un trabajo, y deja que la interfaz de usuario consulte el estado o reciba actualizaciones en streaming, en lugar de mantener una solicitud abierta hasta que termine.

Si la app necesita ejecutar código que no controla, como código escrito por usuarios o generado por un agente, no lo ejecutes en la app. Ejecútalo en Databricks Sandbox, un entorno aislado que puede iniciarse desde una imagen personalizada, para que su uso de CPU y memoria se mantenga fuera de las instancias que atienden a los usuarios.

image4.png

Figura 2: Dónde se ejecuta cada tipo de trabajo y dónde reside el estado.

Planifica para la escala y elige un marco de trabajo

Cuando más personas usan tu app, puedes agregar capacidad de dos maneras: escalar verticalmente pasando a un tamaño de cómputo mayor, lo que da a cada instancia más CPU y memoria, o escalar horizontalmente agregando instancias para compartir la carga de solicitudes. Con trabajo pesado ejecutándose fuera de la app, lo que suele limitarla es cuántas solicitudes puede manejar a la vez.

Por ejemplo, en el caso del Black Friday, cada verificación de stock es ligera, pero las verificaciones de 200 gerentes de tienda pueden llegar juntas en picos. Más instancias distribuyen esas solicitudes, y una instancia más grande ayuda si la app puede usar los núcleos adicionales, normalmente ejecutando más trabajadores. Una app que mantiene un gran conjunto de datos de referencia o modelo en memoria alcanza un límite diferente. Una instancia más grande le da la memoria que necesita; agregar instancias no ayuda, porque cada instancia carga su propia copia. Puedes empezar en Medium y dejar que la prueba de carga más adelante en esta guía muestre cuál necesitas.

El marco de trabajo es más difícil de cambiar más adelante, por lo que vale la pena elegirlo ahora. Databricks Apps ejecuta aplicaciones construidas en Python o Node.js y no estás limitado a los marcos a continuación. Para la mayoría de las nuevas aplicaciones, recomendamos AppKit, el SDK de TypeScript que databricks apps init y las habilidades de agentes de Databricks utilizan por defecto. El almacenamiento en caché, la telemetría, la lógica de reintento y el manejo de errores vienen integrados, lo que te ofrece un punto de partida para varias prácticas de esta guía. AppKit ejecuta un proceso de Node.js por instancia de forma predeterminada, por lo que la forma más sencilla de escalar es agregando instancias.

Si ya tienes una app, o tu back end necesita Python:

  • Front-end de JavaScript con un back-end de API (FastAPI, Flask o Express): mantén el estado de la interfaz de usuario en el navegador y haz que el estado del lado del servidor sea recuperable entre trabajadores e instancias. Los back ends de Python pueden ejecutar varios trabajadores por instancia, por ejemplo con Uvicorn o Gunicorn. Los back ends de Node.js ejecutan un proceso por instancia de forma predeterminada, así que escanéalos agregando instancias.
  • Marcos de trabajo Streamlit o Gradio: buenos para herramientas de datos e IA construidas rápidamente en Python. Streamlit se ejecuta como un solo proceso, y ambos dependen del manejo de sesiones locales de la instancia, así que prueba la continuidad de la sesión durante los reinicios y el escalado. Para aplicaciones que deben escalar entre instancias con una recuperación sin problemas, prefiere uno de los enfoques anteriores, ya que no se recomiendan estos marcos.

Elijas el que elijas, si mantiene el estado de sesión en la memoria del servidor, vale la pena probar qué sucede cuando una sesión se mueve a otra instancia antes de escalar horizontalmente.

Planifica para el estado de la aplicación que sobrevive a reinicios y reescalado

La mayoría de Databricks Apps mantienen algún estado en la memoria, y eso está bien siempre y cuando sepas qué partes puedes permitirte perder. Un primer paso útil es enumerar lo que contiene cada sesión y lo que debe sobrevivir a un reinicio, luego dividirlo en estado blando y duro:

Qué esEstado blandoEstado duro
Qué esDatos de trabajo temporales, mantenidos por velocidad o contextoLa fuente de la verdad, mantenida de forma duradera
EjemplosContexto en memoria, cachés, trabajo en cursoRegistros comerciales, puntos de control, preferencias guardadas
Dónde residePor lo general, memoria de instancia o disco local, vinculado a una instanciaTablas de Lakebase o Unity Catalog, disponibles para cada instancia
Si se pierdeSe reconstruye a partir del estado duro cuando es posibleDebe sobrevivir a reinicios y fallos, dentro de tus necesidades de recuperación

Cómo funciona esa división depende del tipo de app:

  • Agente de IA: mantén el contexto de la conversación, las salidas de herramientas y los planes en el estado blando mientras se ejecuta el bucle, y guarda un punto de control después de cada paso significativo.
  • App de flujo de trabajo: transmite o consulta el estado en curso a la interfaz de usuario y guarda cada paso completado.
  • Panel: mantén los valores de los filtros, las listas de referencia y los pequeños conjuntos de datos en la memoria, y guarda las preferencias del usuario y los filtros guardados como estado duro.

image3.png

Figura 3: Cuando una sesión se mueve, otra instancia puede reconstruirla a partir del estado duro.

Databricks Apps mantiene a cada usuario en la misma instancia sobre la base de un esfuerzo razonable (afinidad de sesión) y reequilibra las sesiones cuando es necesario, por lo que cualquier caché por usuario que tu app mantenga localmente suele permanecer disponible. Los reinicios, los fallos y los cambios de escala aún pueden mover una sesión, por lo que otra instancia debe poder reconstruirla a partir del estado duro (Figura 3).

Construir: escribe código que escale y sobreviva a los reinicios

Con los objetivos y una arquitectura en su lugar, el siguiente paso es escribir código que resista la carga, incluso cuando una sesión se mueve o una instancia se detiene.

Instrumenta la app antes de necesitarla

Recomendamos activar la telemetría desde el principio para que los datos estén disponibles cuando los necesites. La telemetría de aplicaciones escribe registros, seguimientos y métricas en tablas de Unity Catalog a través de OpenTelemetry. Una vez que se habilita para una aplicación, los registros llegan automáticamente, pero los seguimientos y las métricas necesitan instrumentación.

Debes crear tramos personalizados en torno a las llamadas SQL, de bases de datos, de modelos y de API para mostrar a dónde se va el tiempo. Registra también las excepciones capturadas en el tramo para que aparezcan en tus seguimientos. Los identificadores de seguimiento y de solicitud te permiten seguir las solicitudes de un usuario a través de las instancias. Por ejemplo, un tramo alrededor de una llamada SQL:

Usa código asíncrono y elimina las llamadas desperdiciadas

La mayoría de las aplicaciones pasan su tiempo esperando en otro servicio: una consulta SQL, una llamada a un modelo, una API externa. Con las llamadas de bloqueo, cada espera mantiene un espacio de ejecución para toda la llamada. Un puñado de llamadas lentas puede agotar esa capacidad. Es por eso que los controladores asíncronos son importantes para el trabajo con uso intensivo de E/S. Cuando los controladores esperan llamadas a modelos y bases de datos, un trabajador puede seguir atendiendo otras solicitudes mientras espera, siempre que esas llamadas no sean de bloqueo. Tus seguimientos y métricas del sistema mostrarán cuándo se aplica esto: si la mayor parte del tiempo de una solicitud se pasa en tramos SQL, de modelos o de API, y la latencia aumenta con los usuarios concurrentes mientras la CPU se mantiene baja, es probable que las solicitudes se estén poniendo en cola detrás de llamadas de bloqueo.

Incluso con el código asíncrono, una solicitud aun puede ser lenta si ejecuta sus consultas una tras otra. Inicia consultas independientes juntas (por ejemplo, con asyncio.gather o Promise.all), para que la solicitud tarde casi lo mismo que su consulta más lenta. También vale la pena limitar cuántas se ejecutan en paralelo, para que una sola solicitud no sature el almacén o la base de datos. A menudo es mejor combinar consultas que ejecutar consultas N+1, donde la aplicación recupera una lista y luego ejecuta una consulta más por elemento: una cláusula join o IN hace el mismo trabajo en una o dos.

Almacena en caché los datos por usuario de forma predeterminada

Una caché acelera una aplicación, pero también puede filtrar datos: una caché a nivel de aplicación no aplica los permisos de Unity Catalog, por lo que una caché compartida puede mostrar los datos de un usuario a otro. Delimita las claves de caché por la identidad verificada del usuario y los parámetros de consulta, y por sesión cuando sea necesario; nunca utilices como clave una identidad que el cliente envíe sin verificarla. Comparte los datos en caché solo cuando sean idénticos para todos. Para entradas compartidas que muchos usuarios leen a la vez, permite que una solicitud actualice una entrada vencida mientras las demás esperan, para que no accedan todas al almacén juntas. La caché de AppKit, por ejemplo, deduplica los fallos de caché concurrentes dentro de cada instancia.

Sobre los reinicios de contenedores de aplicaciones o cambios de sesión

Llevar el diseño de estado ligero y estado pesado a la práctica se reduce a algunas recomendaciones:

  • Persiste cualquier cosa que deba sobrevivir a un reinicio o implementación. La memoria por sí sola es buena para cachés descartables, pero no para el trabajo que los usuarios no pueden permitirse perder.
  • Crea puntos de control donde no te gustaría repetir el trabajo y haz que los pasos sean idempotentes para que un reintento sea seguro.
  • Haz que las sesiones sean portátiles, para que cualquier instancia pueda reconstruirlas a partir del estado pesado (Figura 3). Vuelve a cargar solo lo que necesites y acáchelo para evitar lecturas repetidas.
  • Las aplicaciones de navegador obtienen afinidad de sesión automáticamente. Para los clientes de API con estado, envía un encabezado X-Routing-Key estable y asígnale como clave aquello que posea el estado ligero. Elige una clave lo suficientemente específica como para distribuir la carga, como una conversación o un ID de usuario en lugar de un ID de inquilino. El cliente configura el encabezado, así que úsalo solo para el enrutamiento, nunca para decidir quién es el usuario.
  • Espera que las conexiones a la base de datos también se caigan. Se caen cuando la base de datos se reinicia o falla. Vuelve a conectar con retroceso acotado y fluctuación, para que las instancias no se reconecten todas a la vez y provoquen una avalancha de conexiones. Antes de reintentar una escritura, verifica la base de datos para confirmar que no se haya completado ya.
  • Mantén el inicio ligero. Cada reinicio, implementación y nueva instancia paga por cargar modelos o conjuntos de datos, calentar cachés y abrir grupos antes de poder atender tráfico. Evita instalaciones grandes y llamadas externas de bloqueo al inicio, y carga recursos pesados solo cuando sea necesario.

Cierra de forma ordenada

Cuando vuelves a implementar una aplicación, Databricks envía SIGTERM, y luego SIGKILL si la aplicación no ha finalizado en un plazo de 15 segundos. Ese período es para los puntos de control finales. El trabajo importante ya debería haberse guardado durante la operación normal.

Como ejemplo, con FastAPI, Uvicorn finaliza las solicitudes abiertas antes de ejecutar la limpieza del ciclo de vida. save_in_progress_sessions() reemplaza tu propia función que guarda el trabajo sin terminar:

Esto asume un grupo asíncrono (por ejemplo, AsyncConnectionPool de psycopg). El tutorial de Apps-to-Lakebase utiliza un grupo síncrono, que cierras sin await.

Configura el --timeout-graceful-shutdown de Uvicorn por debajo de 15 segundos (por ejemplo, 10) para que una solicitud de larga duración no consuma el tiempo del punto de control, y prueba el cierre con tu propia carga de trabajo. El complemento Lakebase de AppKit cierra sus grupos al apagarse; cualquier punto de control personalizado aún debe caber en la misma ventana.

Prueba e implementa: prueba de carga y dimensionamiento para el pico

image2.png

Figura 4: Métricas del sistema durante una prueba de carga escalonada: la latencia aumenta en el último paso mientras la CPU y la memoria se mantienen por debajo de sus límites.

Antes del lanzamiento, una prueba de carga te ayudará a convertir tus estimaciones en decisiones más cercanas a la realidad: el tamaño de la instancia, los trabajadores por instancia y el recuento de instancias.

Cómo realizar pruebas de carga en Databricks Apps

Recomendamos realizar pruebas de carga antes de pasar a producción, utilizando recorridos de usuario reales en tu pico esperado. Una herramienta como Locust informa las solicitudes por segundo, los percentiles de latencia y la tasa de fallos en cada paso, y la prueba se aprueba o falla según los objetivos de latencia y tasa de errores que acordaste para las acciones clave. Mientras se ejecuta la prueba, las métricas del sistema integradas de la aplicación muestran las solicitudes por minuto, la latencia, y la CPU y la memoria frente a sus límites, para que puedas ver qué límite alcanza la aplicación primero (Figura 4).

Aumenta los usuarios concurrentes por pasos hasta que el rendimiento deje de aumentar o la latencia y las tasas de errores rompan tus objetivos. Vale la pena probar varios tamaños de instancia y recuentos de trabajadores, porque una configuración más grande no siempre es más rápida. También sugerimos probar la recuperación en un entorno de prueba: detén e inicia la aplicación, no te limites a volver a implementar o cambiar el recuento de instancias durante una ejecución, luego verifica si los usuarios pueden continuar, cuánto tiempo toma la recuperación y si se perdió algún trabajo. Para las aplicaciones de agentes, la guía de pruebas de carga explica cómo realizar una prueba primero con un LLM simulado para medir el rendimiento de la aplicación, y luego con el modelo real para la latencia de extremo a extremo.

El generador de carga en sí puede ser el cuello de botella: puede quedarse sin CPU o conexiones primero, y los errores de autenticación o las respuestas de límite de velocidad pueden parecer ralentizaciones. Lo que cuenta son las solicitudes exitosas sostenidas dentro de tu objetivo de latencia, no un pico breve.

La prueba de carga también debe mostrar si los servicios detrás de la aplicación se mantienen al día. Si el almacén comienza a ponerse en cola o un punto de enlace del modelo se limita, escala ese servicio, no la aplicación.

Elige el tamaño de la instancia

Databricks Apps ofrece tres tamaños: Medium (el predeterminado, hasta 2 vCPU y 6 GB), Large (hasta 4 vCPU, 12 GB) y XLarge (hasta 12 vCPU, 48 GB). El correcto depende de qué límite alcance primero tu aplicación, así que comienza en Medium y deja que la prueba de carga te muestre:

Qué muestra la prueba de cargaCausa probableQué hacer
Solicitudes lentas con CPU de la aplicación bajaLa aplicación está esperando algo externo o las llamadas bloqueantes retienen a los workersMantén el tamaño. Soluciona primero la consulta, el warehouse, el pool de conexiones o las llamadas bloqueantes, y revisa también la CPU por proceso: un núcleo al máximo puede parecer una CPU baja en general
CPU cerca del límite, el servidor ejecuta varios workers (por ejemplo, FastAPI con Uvicorn)La aplicación puede usar más núcleosCambiar a Grande
CPU cerca del límite, aplicación de un solo proceso (Streamlit o AppKit por defecto)El perfilado muestra que el trabajo depende de un solo núcleoAñade instancias. Un tamaño mayor solo ayuda si la aplicación puede usar núcleos adicionales, por ejemplo, mediante hilos de workers o bibliotecas nativas
Memoria cerca del límiteGrandes conjuntos de datos o modelos en la memoriaSube de tamaño para la memoria: Grande duplica a Mediano, XLarge ofrece 48 GB en una sola instancia
Prueba de recuperación: la aplicación se cae cuando se reinicia su única instanciaNo hay ninguna instancia de reserva para asumir el controlAñade instancias, no un tamaño mayor

¿Cuántos workers debe ejecutar cada instancia?

Los workers son procesos de servidor dentro de cada instancia. Para los servidores de Python que admiten este modelo, configuras la cantidad al iniciar (por ejemplo, uvicorn --workers 2), y se aplica por instancia.

Un solo worker puede dejar la CPU inactiva, pero los workers adicionales también compiten por la CPU y la memoria. En la prueba de rendimiento de nuestra guía de pruebas de carga, Mediano funcionó mejor con dos workers que con cuatro, y Grande ofreció aproximadamente 2,2 veces el rendimiento de Mediano. Considera los puntos de partida documentados (dos workers en Mediano u ocho en Grande) como una primera estimación: la prueba simulaba el modelo de LLM y estaba limitada por la CPU, y una aplicación real que pasa la mayor parte del tiempo esperando llamadas al modelo podría aprovechar mejor los workers adicionales. Elige la cantidad según tus propias pruebas de carga, con el modelo real.

¿Cuántas instancias debe ejecutar la aplicación?

Con el escalado horizontal, tú configuras el número de instancias. El límite predeterminado es de cinco instancias por aplicación, y tu representante de Databricks puede aumentarlo si las pruebas de carga muestran que necesitas más. Ajusta el recuento según los picos esperados y el crecimiento. La aplicación sigue respondiendo mientras cambia el recuento, y el coste de cómputo escala de forma lineal con el número de instancias. Si vas a convertir una aplicación existente, pruébala primero en un duplicado.

Para una mayor disponibilidad, recomendamos al menos dos instancias, con suficiente capacidad para gestionar la carga pico después de perder una: si el pico necesita dos instancias, ejecuta tres. Las instancias adicionales protegen contra el fallo de una instancia, no contra problemas en los servicios que están detrás de la aplicación.

Calcula el presupuesto de conexiones para Lakebase

Para una Databricks App que se conecta a Lakebase con OAuth, recomendamos empezar con un pool de conexiones en el lado de la aplicación utilizando la cadena de conexión estándar de la base de datos (que no sea PgBouncer). Reutiliza las conexiones y obtiene nuevas credenciales de OAuth a medida que abre otras nuevas, tal como muestra el tutorial de Apps a Lakebase para Python. Configura el tiempo de espera del pool para dejar suficiente tiempo para la consulta en sí antes de que venza el plazo de la solicitud.

Esas conexiones se acumulan, así que calcula el presupuesto antes de añadir instancias o workers. Con un pool por worker, el límite superior es instancias × workers por instancia × tamaño máximo del pool: cinco instancias con ocho workers y un pool máximo de diez pueden abrir hasta 400 conexiones. Añade otros clientes y cualquier conexión que la aplicación abra en nombre de los usuarios, y luego compara el total con el límite documentado de la base de datos, dejando margen para los despliegues cuando las versiones antiguas y nuevas se ejecutan en paralelo.

Las consultas en nombre del usuario (OBO) necesitan capacidad de identidad. Esto significa que cada usuario que consulta Lakebase como sí mismo necesita su propio rol de Postgres, y Lakebase permite 500 roles por rama. Para bases de usuarios más grandes, decide pronto qué consultas realmente necesitan acceso por usuario. Añadir instancias no cambia este límite. Cuando los permisos a nivel de grupo son suficientes, un rol de Postgres para un grupo de Databricks permite a sus miembros conectarse con sus propios tokens OAuth, por lo que un solo rol cubre a todo el grupo.

Implementa sin tiempo de inactividad y revierte de forma segura

Para aplicaciones escaladas horizontalmente, Databricks actualiza una instancia primero y el resto después de que tenga éxito, de modo que la aplicación sigue funcionando. Aun así, vale la pena comprobar después de cada despliegue que la aplicación está sana y que las sesiones se recuperan. Mantener el código en Git significa que puedes revertir volviendo a desplegar una etiqueta o commit conocido y correcto. Durante una implementación, las versiones antigua y nueva se ejecutan en paralelo, así que asegúrate de que los formatos de la base de datos y de los puntos de control sean legibles por ambas, y no elimines campos que la versión anterior necesite hasta que estés seguro de que no vas a hacer una reversión.

Operaciones: supervisa, diagnostica y soluciona problemas a partir de los datos

Tras el lanzamiento, el trabajo se convierte en un bucle: encuentra el paso más lento, arréglalo y vuelve a medir. Por eso mantenemos la telemetría activada en producción. En las aplicaciones escaladas horizontalmente, la vista en directo (Live) en la pestaña Registros (Logs) muestra una instancia a la vez; con la telemetría habilitada, los Registros de telemetría de la aplicación muestran todas ellas.

Cuando algo vaya lento, rastrea la solicitud de principio a fin (Figura 5).

image5.png

Figura 5: Dónde invierte su tiempo una solicitud y los principales cuellos de botella.

Empieza por el síntoma

Estos son los síntomas que vemos con más frecuencia y hacia dónde suelen apuntar:

SíntomaDónde buscarCausa probableQué hacer
Primera solicitud lenta tras un periodo de inactividad o un despliegueMétricas del sistema y trazas en la telemetría de la aplicación en la pestaña InsightsInicio en frío: inicio de la aplicación o un servicio que se despierta tras estar inactivoComprueba el tiempo de inicio de la aplicación y si Lakebase o el SQL warehouse se detienen cuando están inactivos, y mantén el inicio ligero
Solicitudes lentas con CPU de la aplicación bajaMétricas del sistema y trazas en la telemetría de la aplicación en la pestaña InsightsLa aplicación está esperando algo externo o las llamadas bloqueantes retienen a los workers

Comprueba las trazas en busca de retrasos en las consultas, el warehouse o el pool de conexiones antes de añadir capacidad de cómputo a la aplicación

Para aplicaciones de un solo proceso, ten en cuenta que una CPU baja en general puede seguir significando que un núcleo está al máximo

CPU o memoria de la aplicación cerca del límiteMétricas del sistema en la pestaña InsightsLa aplicación en sí es el cuello de botella o almacena demasiado en la memoriaAnaliza el trabajo que consume mucha CPU, saca los estados grandes de la memoria y consulta la guía en "Elige el tamaño de instancia"
Tiempo de espera agotado al buscar una conexión con la base de datosRegistros de la aplicación y métricas de LakebaseContención en el pool, transacciones largas o límites de conexiones a la base de datosInspecciona el uso de conexiones y la duración de las transacciones, y luego ajusta los pools o la capacidad de la base de datos dentro del presupuesto de conexiones
Los usuarios pierden su trabajo o ven errores durante los despliegues o el reescaladoMétricas del sistema en la pestaña InsightsEstado volátil que no se puede reconstruir, o un apagado que no termina en 15 segundosEstablece puntos de control para el trabajo importante, haz que las sesiones se puedan reconstruir en cualquier instancia y prueba el apagado con tus solicitudes y flujos reales

Configura alertas de estado

Recomendamos planificar las alertas como parte de la configuración: decide quién recibe una notificación cuando la aplicación se cae, y alimenta app_status.state y compute_status.state desde la Apps API hacia tu herramienta de supervisión. El estado de la aplicación por sí solo no demuestra que los usuarios puedan trabajar, así que comprueba también una ruta de usuario representativa, con su latencia y tasas de error. Deja margen para pequeños cambios de estado durante los despliegues cuando establezcas los umbrales.

Resumen

Escalar Databricks Apps implica dimensionar toda la ruta de las solicitudes, no solo el servidor de aplicaciones: establece objetivos de latencia y de carga máxima, envía el trabajo pesado al servicio diseñado para ello, mantén el estado recuperable y deja que las pruebas de carga y la telemetría decidan a dónde va la capacidad. Añade cómputo cuando las mediciones muestren que lo necesitas, no como primera reacción.

Para profundizar más, lee cómo crear aplicaciones de datos e IA listas para producción con Databricks Apps y Lakebase. Para obtener más detalles, consulta Buenas prácticas para Databricks Apps y Registro y supervisión para Databricks Apps en la documentación. Para ver patrones de arquitectura según el tipo de aplicación (como herramientas internas, copilotos de IA y flujos de trabajo de agentes), echa un vistazo a Creación de mejores aplicaciones y Aplicaciones con estado para miles de usuarios del Data + AI Summit 2026.

Preguntas frecuentes

¿Cómo escalo una Databricks App?

Escálala en cuatro etapas: diseño, construcción, pruebas y despliegue, y operaciones. Establece primero los objetivos de latencia y carga máxima, reserva el cómputo de la aplicación para servir la interfaz de usuario y escribe código asíncrono con un estado recuperable. Luego, deja que las pruebas de carga y la telemetría decidan si debes escalar verticalmente a una instancia más grande o horizontalmente a más instancias.

¿Debo escalar vertical u horizontalmente mi Databricks App?

Depende de qué límite alcance la aplicación primero. Escala horizontalmente añadiendo instancias cuando las solicitudes llegan en ráfagas o una aplicación de un solo proceso está limitada a un núcleo. Escala verticalmente a Large o XLarge cuando la aplicación necesite más memoria, o cuando ejecute varios workers que puedan usar núcleos adicionales.

¿Qué tamaños de instancia ofrece Databricks Apps?

Databricks Apps ofrece Medium (el predeterminado, hasta 2 vCPUs y 6 GB), Large (hasta 4 vCPUs y 12 GB) y XLarge (hasta 12 vCPUs y 48 GB). Comienza con Medium y deja que una prueba de carga muestre qué tamaño necesita tu aplicación.

¿Cómo mantengo las sesiones de usuario funcionando cuando una aplicación se reinicia o escala?

Divide el estado de la sesión en estado blando, que se puede reconstruir, y estado duro, que se almacena de forma duradera en tablas de Lakebase o Unity Catalog. Databricks Apps mantiene a cada usuario en la misma instancia en la medida de lo posible, pero los reinicios y el escalado aún pueden mover una sesión, por lo que cualquier instancia debe poder reconstruirla a partir del estado duro.

¿Cuántas conexiones a Lakebase puede abrir una aplicación escalada?

Con un pool por worker, el límite superior es instancias × workers por instancia × tamaño máximo del pool. Por ejemplo, cinco instancias con ocho workers y un máximo de pool de diez pueden abrir hasta 400 conexiones. Compara ese total con el límite documentado de la base de datos y deja margen para los despliegues.

¿Listo para llevar tu aplicación de unos pocos usuarios a miles? Consulta las Buenas prácticas para Databricks Apps y el escalado horizontal para Databricks Apps en la documentación.

"Explorar Databricks Apps" →

(Esta entrada del blog ha sido traducida utilizando herramientas basadas en inteligencia artificial) Publicación original

Etiquetas relacionadas:

MEJORES PRÁCTICAS

Recibe las últimas publicaciones en tu bandeja de entrada

Suscríbete a nuestro blog y recibe las últimas publicaciones directamente en tu bandeja de entrada.