1 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • La clave de la ejecución durable no es la infraestructura en sí, sino la preservación del estado del flujo de trabajo; si se conserva el progreso, es posible reejecutar y recuperar
  • Obelisk guarda el progreso del flujo de trabajo en un log de ejecución y lo reproduce desde el historial persistido, con una estructura adaptada al reintento de actividades
  • SQLite ofrece estado durable basado en transacciones en un archivo local, sin un servicio de base de datos separado, saltos de red ni un plano de control adicional
  • Litestream transmite de forma asíncrona los cambios de SQLite a un almacenamiento de objetos compatible con S3, pero si el volumen desaparece antes de la copia, se pueden perder las escrituras más recientes
  • Obelisk también soporta Postgres, que resulta más adecuado cuando se necesita mayor disponibilidad, escalabilidad compartida o características propias de una base de datos en red

Modelo operativo de SQLite y Litestream

  • Litestream puede transmitir de forma asíncrona los cambios de SQLite a un almacenamiento de objetos compatible con S3
  • Permite mantener el estado de trabajo cerca del entorno de ejecución y, al mismo tiempo, copiar la base de datos hacia afuera para respaldos, migraciones o inspección
  • Debido a la naturaleza de la replicación asíncrona, si el volumen de SQLite desaparece antes de copiarse, al restaurar se pueden perder las escrituras locales más recientes
  • La estructura consiste en ejecutar el servidor de Obelisk junto con la base de datos SQLite, respaldarlo con Litestream y hacer que un observador obtenga la base de datos necesaria cuando haga falta
  • El mismo archivo SQLite puede usarse para reproducción local, depuración y para entender qué hizo realmente el agente

Casos adecuados de uso y criterios para elegir Postgres

  • Los agentes de IA y los flujos de trabajo generados por IA suelen ser ráfagos y, en muchos casos, experimentales, por lo que una configuración con pequeñas unidades de estado propias por agente o por tenant es más fácil de entender
  • Tener varios servidores pequeños dentro de micro-VMs o contenedores, cada uno con su propia base de datos SQLite y respaldo en almacenamiento de objetos, puede ser más simple, más barato y ofrecer mejor aislamiento de fallos que un único sistema grande, compartido y siempre en ejecución
  • Si la replicación asíncrona hacia almacenamiento de objetos no encaja con el modelo de durabilidad deseado, o si se necesita mayor disponibilidad, una escalabilidad compartida más amplia o características de una base de datos en red, Postgres es más apropiado
  • Muchos sistemas de flujos de trabajo no necesitan ese nivel de infraestructura desde el primer día, y no hace falta empezar con una infraestructura mayor que los requisitos del estado
  • Con solo una base de datos SQLite local, respaldo de Litestream hacia S3 y una combinación de workers de bajo costo, se puede construir un sistema durable con poca infraestructura, y en el ámbito de los agentes de IA puede ser una opción razonable por defecto

1 comentarios

 
GN⁺ 4 시간 전
Comentarios de Hacker News
  • Empecé a armar flujos de trabajo con Temporal y, para una app local, se despliega de forma bastante ligera; en instalaciones locales aisladas usa SQLite
    Manejar reintentos de API y la limpieza de flujos de trabajo y tareas se volvió realmente simple, así que recomendaría probarlo. Filosóficamente, va exactamente en la misma dirección que propone este artículo, pero además le suma una interfaz muy rica y flexible que resulta muy cómoda para que la manejen agentes. También es fácil revisar los flujos de trabajo en la interfaz web e inspeccionar la ejecución de agentes
    Temporal le agrega al sistema un nivel de confiabilidad mucho mayor casi gratis. Los sistemas distribuidos y confiables son difíciles, así que me parece mejor no reinventar la rueda
    Si quieres poder inspeccionar fácilmente una base de datos SQLite, entender qué está pasando en un flujo de trabajo, componer tareas individuales y hacer que un flujo de trabajo se pueda invocar de forma simple, vale la pena mirar Temporal
    Junto con eso, casi dejé de usar archivos para agentes. Markdown y JSON están bien, pero al crear apps locales pequeñas se sienten como una trampa. Los LLM manejan bien SQLite, y desde ahí puedes renderizar a Markdown, JSON o cualquier otro formato que quieras. Si el agente puede consultar solo filas específicas en vez de levantar jq o hacer grep sobre Markdown, también ahorras muchos tokens. Obtienes un sistema de gestión de datos portátil y autocontenido que además te obliga a dar una estructura más disciplinada a los datos en vez de repartirlos entre varios archivos. Y si un proyecto local pequeño crece o se formaliza más, también puede pasar a MySQL/Postgres, ya con esquema y disciplina de datos establecidos

    • Suena a que lo corres principalmente en una sola máquina
      Temporal se vuelve mucho más complejo cuando escala. Operar Cassandra no es nada agradable, y Ringpop y TChannel son difíciles de depurar cuando surge algún problema. El soporte de backend SQL no admite réplicas con escalado horizontal por los requisitos de consistencia, así que solo es posible una única instancia
      Dependiendo de cómo escribas el código, también se vuelve complejo modificar código incrustado en los flujos de trabajo. Los cambios que alteran el orden de eventos del historial rompen el determinismo de workers ya desplegados
      Nosotros usamos mucho Temporal; a todos los que empezaron con scripting simple o automatización les encanta, y a todos los que construyeron sistemas reales de producción encima les desagrada. Puede ser falta de madurez operativa, pero la imagen tan color de rosa que se ve en estos comentarios no coincidió con mi experiencia
    • Por lo que se oye en HN, terminas pagando más de lo esperado por la solución administrada de Temporal o, al final, teniendo que operar tú mismo un sistema muy pesado y cargar con una importante sobrecarga operativa
      No lo he hecho personalmente, pero me gustaría escuchar más experiencias reales
    • ¿Podrías dar un ejemplo concreto de usar SQLite en lugar de hacer jq o grep sobre Markdown?
    • Parece publicidad de Temporal :)
    • Me parece interesante la discusión entre el enfoque con archivos y el enfoque con base de datos. Yo también fui y vine entre ambos, pero al final terminé quedándome con la base de datos
  • No entiendo la obsesión con usar SQLite en apps reales de producción. SQLite es una base de datos embebida, así que no encaja en absoluto para manejar concurrencia
    Para eso existen servidores de bases de datos como Postgres o MySQL. Todo su propósito es permitir que múltiples procesos modifiquen datos al mismo tiempo desde distintas máquinas
    Este es un principio básico de la informática, así que quienes repiten “SQLite para todo” parecen tener algo de falta de experiencia

    • Parece haber una comprensión bastante limitada de qué tipos de concurrencia existen y cómo satisfacer esos requisitos. Que sea un servidor o no, en realidad no es tan importante en esta discusión
      SQLite es una excelente base de datos de producción para muchas cargas de trabajo reales, y eso está ampliamente documentado. Como es muy diferente de Postgres, hay que aprender una tecnología completamente distinta
      Una forma de verlo es que SQLite puede encajar muy bien en partes de un sistema donde de forma natural hay una partición fuerte
    • Solo con SQLite y un frontend concurrente, por ejemplo un servidor net/http de Go, muchas veces basta para manejar toda la carga que un servicio pueda imaginar. Más aún si con el tiempo puedes escalar el hardware, y SQLite puede escalar fácilmente hasta cientos de miles de TPS
      Lo que realmente se sacrifica es alta disponibilidad/failover y recuperación ante desastres, aunque también hay soluciones para eso. Los sistemas de servidor único suelen ser sorprendentemente robustos, porque cuando no hay un plano de control complejo, muchas veces la disponibilidad baja a medida que el sistema crece
    • SQLite es bueno para muchos usos, pero parece que probablemente pasas la mayor parte de tu tiempo con apps web grandes que requieren bases de datos en red y sharding. Ese también es un campo interesante, pero hay muchos otros
      Me gusta reevaluar las “mejores prácticas” tradicionales a la luz de los cambios tecnológicos, sobre todo si eso aumenta la simplicidad. Tener un sitio de redes sociales familiar corriendo sobre una sola DB SQLite en un VPS es excelente. Son como 15 usuarios y casi no requiere mantenimiento. También tengo una instancia de FreshRSS y una página “now” corriendo sobre SQLite
      En el trabajo también he usado SQLite para todo tipo de cosas durante las últimas décadas. Lo he usado para colas de trabajo temporales, para cargar y consultar rápidamente muchos logs en local, y para mostrarlos y filtrarlos en tiempo real con el excelente https://github.com/simonw/datasette de simonw
      Más que “SQLite para todo”, yo lo vería como “SQLite para muchas más cosas de las que uno cree”
      El trabajo de kentonv/Cloudflare con SQLite en el edge puede haber popularizado un poco más esta idea, pero la tendencia ya existía. https://blog.cloudflare.com/sqlite-in-durable-objects/
      Querer conocer y aprovechar estos casos pequeños pero útiles no es falta de experiencia; de hecho, puede ser una señal de experiencia
    • ¿Por eso existen miles de millones de bases de datos SQLite, no?
      Es muy probable que SQLite se use más que todos los demás motores de bases de datos juntos. Hay miles de millones de copias de SQLite en el mundo real. Está en dispositivos Android, iPhone y otros equipos iOS, Mac, instalaciones de Windows 10/11, Firefox/Chrome/Safari, Skype, iTunes, el cliente de Dropbox, TurboTax y QuickBooks, PHP y Python, la mayoría de las TVs y set-top boxes, la mayoría de los sistemas multimedia de autos y en una cantidad incontable de aplicaciones
      https://sqlite.org/mostdeployed.html
    • Si los datos se shardean de forma natural y las escrituras ocurren dentro de un solo shard, entonces el paralelismo se vuelve fácil. Las solicitudes se enrutan al shard donde están los datos del usuario, y ahí se lee y escribe localmente
      Eso hace que la escalabilidad sea mucho más fácil de entender. Solo hay que dividir y repetir; agregas un shard más cada N usuarios
      A cambio obtienes otros problemas, como consultas entre shards, por ejemplo para analítica, y cómo nivelar la carga cuando los usuarios se van o envejecen
      Pero sí puedes evitar todo el problema de escalar índices compartidos generados por inserciones/actualizaciones cuando tienes una gran cantidad de usuarios
      Termina siendo más una base de datos jerárquica que una base de datos relacional
  • Reemplazó todo esto con Go + SQLite: Intercom, Zendesk, email marketing, Kanban, Todo, stack de pagos, issue tracker, foro, monitor de uptime, clon de PagerDuty
    Como vende decenas de productos, pensó: ¿y si construyo todo yo mismo?
    Todo corre en el mismo servidor y usa muy poca memoria. Reemplazó por completo las herramientas SaaS que usaba con estas alternativas
    Al migrar a un servidor dedicado, bajó el costo a cerca de 1/10 de lo que pagaba por soluciones cloud administradas, con la misma alta disponibilidad y además menor latencia. Parte del motivo era que los noisy neighbors en el VPS aumentaban la tail latency
    Antes gastaba mucho dinero en estas cosas, pero ya lleva 4 meses operándolo y solo ha necesitado actualizaciones menores
    El despliegue es realmente simple. Sin Docker ni Kubernetes, solo servicios de systemd y binarios compilados en la máquina de desarrollo y luego desplegados
    También pagaba por servicios como MaxMind o IPData, pero creó su propio servicio de geolocalización IP y en pruebas rindió mejor que la mayoría de las soluciones existentes
    Empezó reemplazando Uptime Robot, luego ganó confianza y reemplazó PagerDuty. Después reemplazó Intercom
    Por último, siempre había escuchado “no construyas tu propio stack de pagos”, pero pensó YOLO y decidió cometer ese error por su cuenta. Estudió las soluciones de pago existentes, desarrolló y desplegó la suya, y hasta ahora no ha tenido ningún problema
    Delante puso Caddy
    Se dio cuenta de que, de lo que ofrecen la mayoría de los productos SaaS, en realidad solo usaba entre 1% y 5%, y que justo las funciones que sí necesitaba quedaban cada vez más enterradas dentro de estas plataformas “enterprise”, dificultando el flujo de trabajo
    No va a mostrar los productos comerciales porque a sus socios y clientes probablemente no les gustaría saber lo barato que le sale, pero él lo llama ser ingenioso
    Sí puede mostrar una app gratuita. La lanzó recientemente y ya tiene más de 20 mil usuarios: https://macrocodex.app/
    Esta app solo usa el clon de Zendesk. El email lo maneja con enrutamiento de Cloudflare, así que el costo operativo es casi nulo

    • Construiste tu propio monitor de uptime, pero ¿cómo manejas de forma distinta la distribución regional o las pruebas desde conexiones residenciales?
  • Hay una gran distancia entre un archivo y una base de datos con múltiples particiones. No es de mi gusto correr una base de datos en contenedores cuando hay producción real de por medio
    Personalmente, mucho ETL puede procesarse localmente sin traer una base de datos enterprise. En esos casos, DuckDB es entre 5 y 10 veces mejor que SQLite, y mucho más simple y rápido que levantar una base de datos Postgres dedicada
    Para scripting general, no hay comparación entre un script de awk de 20 líneas y su equivalente en SQL sobre DuckDB, mucho más limpio, robusto y mantenible
    Ojalá MotherDuck no termine haciendo pump and dump para llegar a un IPO. Sería triste perder esta herramienta por la típica codicia corporativa

    • Soy developer relations en DuckDB. Primero, gracias por los buenos comentarios :)
      Lo del script de awk de 20 líneas es interesante. Ayer en Ubuntu Summit hice casi el mismo argumento. A partir de cierto punto, escribir shell scripts con GNU coreutils se vuelve poco realista, y los scripts SQL en DuckDB escalan mucho mejor en complejidad, mantenibilidad y, a menudo, también en rendimiento. Las diapositivas están aquí: https://blobs.duckdb.org/slides/duckdb-ubuntu-summit-2026.pd... páginas 32–36
      Además, MotherDuck desarrolla un DBaaS de código cerrado sobre DuckDB. Está construido sobre DuckDB, y DuckDB puede conectarse a MotherDuck, pero es una empresa separada con inversión de VC y sede en Seattle
      DuckDB lo desarrolla DuckLabs, una empresa bootstrappeada de Ámsterdam, es decir, basada en ingresos. La propiedad intelectual del proyecto pertenece a una tercera organización, la fundación neerlandesa sin fines de lucro DuckDB Foundation. Más detalles en https://duckdb.org/faq#how-are-duckdb-the-duckdb-foundation-...
  • Creé una librería[0] que permite hacer actualizaciones concurrentes de forma segura sobre una DB SQLite en S3
    Usa la poco conocida extensión SQLite sessions y compare-and-swap de S3 sobre un pequeño archivo de metadatos para lograr un funcionamiento bastante eficiente y seguro. La uso con gusto en varios proyectos pequeños donde necesito una DB con estado para funciones Lambda, pero no quiero pagar el costo de una instancia completa de base de datos
    [0]: https://github.com/psanford/s3db

  • SQLite tiene un rendimiento sorprendentemente bueno frente a Postgres en aplicaciones de un solo nodo
    Postgres usa mucha más memoria y la E/S tiene que pasar por comunicación entre procesos. SQLite, en cambio, puede mantener todo dentro del proceso mediante un pool de conexiones compartido
    Estoy probando varios motores de almacenamiento para un agent harness, y con SQLite pude llegar a 7.5 mil sesiones concurrentes en un solo vCPU, mientras que Postgres se caía o se quedaba sin conexiones
    [0] https://github.com/impalasys/talon/pull/23#issuecomment-4577...

    • Si lo usas bien, SQLite es básicamente una llamada a método dentro del proceso. Si los únicos obstáculos que quedan son el runtime, el kernel, el sistema de archivos y el almacenamiento NVMe local, puede ser brutalmente más rápido que las alternativas alojadas
      En cuanto sales del hilo actual, ya es una batalla perdida en términos de latencia. Si no fuerzas comunicación entre hilos, SQLite puede operar en escalas de microsegundos
    • Suponiendo que SQLite sea software realmente excelente, ¿no sería de esperarse que rindiera bien comparado con Postgres en una aplicación de un solo nodo?
      En el contexto de un solo nodo, Postgres es demasiado. No debería esperarse que compita con SQLite
      Es casi como benchmarkear un HashMap en memoria contra Redis y sorprenderse de que el HashMap salga mejor en condiciones ideales
  • Después de leer sobre SQLite durante años, lo probé en un proyecto personal y, viniendo de usar Postgres, me impactó lo pobre que es su sistema de tipos
    De verdad es muy inferior, no entiendo por qué recibe tantos elogios
    https://sqlite.org/datatype3.html
    https://www.postgresql.org/docs/current/datatype.html
    La experiencia al manejar fechas/horas se siente como usar una base de datos de hace 30 años, y al insertar no se fuerza prácticamente nada. Alguien tendría que explicar por qué a tanta gente le gusta

    • Se pueden usar tablas STRICT: https://sqlite.org/stricttables.html
    • Sí, de hecho es prácticamente la única cosa que me molesta de SQLite. SQLite con un sistema de tipos estricto sería excelente
    • Esto es culpa y costo de la compatibilidad hacia atrás. La mayoría de los usuarios de SQLite debería ejecutar algunos pragma en cada conexión
      PRAGMA journal_mode = WAL
      PRAGMA foreign_keys = ON

      Something non-null

      PRAGMA busy_timeout = 1000

      This is fine for most applications, but see the manual

      PRAGMA synchronous = NORMAL

      If you use it as a file format

      PRAGMA trusted_schema = OFF
      Dependiendo del binding, puede que hagan falta opciones adicionales. Por ejemplo, una aplicación en Python no debería usar los valores por defecto del módulo sqlite3. Esos valores por defecto están simplemente mal. Antes de 3.12 ni siquiera había alternativa aparte de usar un binding fuera de la biblioteca estándar: https://docs.python.org/3/library/sqlite3.html#transaction-c...
      También hay que usar tablas strict. https://www.sqlite.org/stricttables.html
      La usabilidad es mala, pero también se pueden usar restricciones CHECK. Por ejemplo, con el soporte de fechas integrado de SQLite se puede, pero es incómodo:
      CHECK (
      date(my_date_col) IS NOT NULL
      AND my_date_col = date(my_date_col)
      )
      Se necesita el IS NOT NULL porque date devuelve NULL con fechas inválidas. La otra verificación es porque también acepta días julianos; por ejemplo, date('2026') se convierte en algún momento del año 4707 a. C.
    • Porque es un solo archivo
    • Recibe elogios por otras cosas que no son el sistema de tipos
      En especial antes de las tablas strict, coincido en que era decepcionante
      Hay que ver DuckDB. Se acerca a SQLite pero con tipos de verdad. Eso sí, en lugar de OLTP, o sea arreglo de structs, es OLAP, o sea struct de arreglos, así que bajo cargas típicas de SQLite podría rendir peor. En la práctica, si una aplicación está considerando una u otra, probablemente no haya una gran diferencia
  • Después de usar varios clústeres grandes de Postgres, me cambié a SQLite, y un servicio con 7 cifras de usuarios activos mensuales está sostenido por durable objects de SQLite
    Hay que pensar distinto los patrones de acceso, pero las ventajas valieron totalmente la pena

  • Es un buen encuadre. Si el problema principal es almacenar de forma durable el estado del flujo de trabajo, poder inspeccionarlo y recuperarlo fácilmente, muchas veces SQLite basta

  • Tengo ganas de ver pronto la siguiente iteración de esta idea: “para flujos de trabajo durables solo hace falta un log

    • No hace falta esperar más. Ya está pasando
      Una razón por la que una solución del tipo “solo hace falta un log” puede fallar es cuando un log no confiable se convierte en un ataque por inyección[1]
      Hay que revisar el SBOM, y no olvidar incluir también el pipeline de CI/CD[2]
      [1] https://news.ycombinator.com/item?id=48315440
      [2] https://github.com/jqwik-team/jqwik/issues/708#issuecomment-...
    • Hablando en serio, sí compraría la idea de que “para flujos de trabajo durables solo hace falta S3” y la usaría para aplicaciones de procesamiento de datos que mueven datos de S3 a S3
    • ¿De verdad basta un log para flujos de trabajo durables? Me confunde. ¿Cómo persistes y consultas datos anidados o relacionados encima del log? ¿Aquí “log” se refiere a algo como Elasticsearch o Meilisearch?
    • Luego vendrá “para flujos de trabajo durables solo hace falta un socket”, y al final “para flujos de trabajo durables solo hacen falta primitivas del kernel”
      Hablando en serio, ser experto es usar la herramienta adecuada para el trabajo