13 comments

  • e12e2 hours ago
    Interesting idea. It seems like zodb (<a href="https:&#x2F;&#x2F;zodb.org" rel="nofollow">https:&#x2F;&#x2F;zodb.org</a>) might enable some similar things for python - by simply being an object database?<p>Is it possible to mix typescript and python steps?
  • CMCDragonkai1 day ago
    Could you genericise the requirement in postgresql and provide a storage interface we could plug into? I think I have a use for this in Polykey (<a href="https:&#x2F;&#x2F;GitHub.com&#x2F;MatrixAI&#x2F;Polykey">https:&#x2F;&#x2F;GitHub.com&#x2F;MatrixAI&#x2F;Polykey</a>) but we use rocksdb (transactional key value embedded db).
    • KraftyOne1 day ago
      That&#x27;s definitely worth considering! The core algorithms can work with any data store. That said, we&#x27;re focused on Postgres right now because of its incredible support and popularity.
      • CMCDragonkai1 day ago
        You could imagine this working well for cloudflare workers - especially with time limits on execution. (Or with even aws compute market)
    • CMCDragonkai1 day ago
      Also this reminds me of orthogonal persistence <a href="https:&#x2F;&#x2F;wiki.c2.com&#x2F;?TransparentPersistence" rel="nofollow">https:&#x2F;&#x2F;wiki.c2.com&#x2F;?TransparentPersistence</a><p>Did you do literature research of Smalltalk?
  • qianli_cs1 day ago
    Hello! I&#x27;m a co-founder at DBOS here and I&#x27;m happy to answer any questions :)
    • sarahdellysse1 day ago
      Hi there, I think I might have found a typo in your example class in the github README. In the class&#x27;s `workflow` method, shouldn&#x27;t we be `await`-ing those steps?
    • nahuel0x1 day ago
      Can you change the workflow code for a running workflow that already advanced some steps? What support DBOS have for workflow evolution?
      • KraftyOne1 day ago
        It&#x27;s not recommended--the assumed model is that every workflow finishes on the code version it started. This is managed automatically in our hosted version (DBOS Cloud) and there&#x27;s an API for self-hosting: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-hosting" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-...</a><p>That said, we know sometimes you have to do surgery on a long-running workflow, and we&#x27;re looking at adding better tooling for it. It&#x27;s completely doable because all the state is stored in Postgres tables (<a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables</a>).
    • ilove1968841 day ago
      I know this this might sound scripted or can be considered cliche but what is the use case for DBOS.
      • qianli_cs1 day ago
        The main use case is to build reliable programs. For example, orchestrating long-running workflows, running cron jobs, and orchestrating AI agents with human-in-the-loop.<p>DBOS makes external asynchronous API calls reliable and crashproof, without needing to rely on an external orchestration service.
    • peterkelly1 day ago
      How do you persist execution state? Does it hook into the Python interpreter to capture referenced variables&#x2F;data structures etc, so they are available when the state needs to be restored?
      • KraftyOne1 day ago
        That work is done by the decorators! They wrap around your functions and store the execution state of your workflows in Postgres, specifically:<p>- Which workflows are executing<p>- What their inputs were<p>- Which steps have completed<p>- What their outputs were<p>Here&#x27;s a reference for the Postgres tables DBOS uses to manage that state: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables</a>
        • CMCDragonkai1 day ago
          All of this seems it would fit any transactional key value structure.
    • mnembrini1 day ago
      About workflow recovery: if I&#x27;m running multiple instance of my app that uses DBOS and they all crash, how do you divide the work of retrying pending workflows?
      • qianli_cs1 day ago
        Each workflow is tagged by the executor ID that runs it. You can command each new executor to handle a subset of the pending workflows. This is done automatically on DBOS Cloud. Here&#x27;s the self-hosting guide: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-hosting" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-...</a>
    • Dinux1 day ago
      Hai, really cool project! This is something I can actually use.
    • gbuk20131 day ago
      FYI the “Build Crashproof Apps” button in your docs doesn’t do anything.
      • qianli_cs1 day ago
        You&#x27;ll need to click either the Python or TypeScript icon. We support both languages and will add more icons there.
        • gbuk20131 day ago
          Thanks the icons work!<p>I was originally looking at the docs to see if there was any information on multi-instance (horizontally scaled) apps. Is this supported? If so, how does that work?
          • qianli_cs23 hours ago
            Yeah, DBOS Cloud automatically (horizontally) scales your apps. For self-hosting, you can spin up multiple instances and connect them to the same Postgres database. For fan-out patterns, you may leverage DBOS Queues. This works because DBOS uses Postgres for coordination, rate limiting, and concurrency control. For example, you can enqueue tasks that are processed by multiple instances; DBOS makes sure that each task is dequeued by one instance.<p>Docs for Queues and Parallelism: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;queue-tutorial" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;queue-tutorial</a>
  • swyx1 day ago
    &gt; What’s unique about DBOS’s take on durable execution (compared to, say, Temporal) is that it’s implemented in a lightweight library that’s totally backed by Postgres. All you have to do to use DBOS is “npm install” it and annotate your program with decorators. The decorators store your program’s execution state in Postgres as it runs and recover it if it crashes. There are no other dependencies you have to manage, no separate workflow server–just your program and Postgres.<p>this is good until you the postgres server fills up with load and need to scale up&#x2F;fan out work to a bunch of workers? how do you handle that?<p>(disclosure, former temporal employee, but also no hate meant, i&#x27;m all for making more good orcehstration choices)
    • KraftyOne1 day ago
      That&#x27;s a really good question! Because DBOS is backed by Postgres, it scales as well as Postgres does, so 10K+ steps per second with a large database server. That&#x27;s good for most workloads. Past that, you can split your workload into multiple services or shard it. Past that, you&#x27;ve probably outscaled any Postgres-based solution (very few services need this scale).<p>The big advantages of using Postgres are:<p>1. Simpler architecturally, as there are no external dependencies.<p>2. You have complete control over your execution state, as it&#x27;s all on tables on your Postgres server (docs for those tables: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables#system-tables" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables#system-tabl...</a>)
      • reissbaker1 day ago
        Unaffiliated with DBOS but I agree that Postgres will scale much further than most startups will ever need! Even Meta still runs MySQL under the hood (albeit with a very thick layer of custom ORM).
  • chatmasta1 day ago
    Do you consider ”durability” to include idempotency? How can you guarantee that without requiring the developer to specify a (verifiable) rollback procedure for each “step?” If Step 1 inserts a new purchase into my local DB, and Step 2 calls the Stripe API to “create a new purchase,” what if Step 2 fails (even after retries, eg maybe my code is using the wrong URL or Stripe banned me)? Maybe you haven’t “committed” the transaction yet, but I’ve got a row in my database saying a purchase exists. Should something clean this up? Is it my responsibility to make sure that row includes something like a “transaction ID” provided by DBOS?<p>It just seems that the “durability” guarantees get less reliable as you add more dependencies on external systems. Or at least, the reliability is subject to the interpretation of whichever application code interacts with the result of these workflows (e.g. the shipping service must know to ignore rows in the local purchase DB if they’re not linked to a committed DBOS transaction).
    • KraftyOne1 day ago
      Yes, if your workflow interacts with multiple external systems and you need it to fully back out and clean up after itself after a step fails, you&#x27;ll need backup steps--this is basically a saga pattern.<p>Where DBOS helps is in ensuring the entire workflow, including all backup steps, always run. So if your service is interrupted and that causes the Stripe call to fail, upon restart your program will automatically retry the Stripe call and if that doesn&#x27;t work, back out and run the step that closes out the failed purchase.
  • atsbbg13 hours ago
    What are the limits on Retroaction? Can Retroactive changes revise history?<p>For example, if I change the code &#x2F; transactions in a step, how do you reconcile what state to prepare for which transactions. For example, you&#x27;ll need to reconcile deleted and duplicated calls to the DB?
    • KraftyOne11 hours ago
      Generally we recommend against retroaction--the assumed model is that every workflow finishes on the code version it started. This is managed automatically in our hosted version (DBOS Cloud) and there&#x27;s an API for self-hosting: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-hosting" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-...</a><p>That said, we know sometimes you have to do surgery on a long-running workflow, and we&#x27;re looking at adding better tooling for it. It&#x27;s completely doable because all the state is stored in Postgres tables (<a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;explanations&#x2F;system-tables</a>).
  • mfrye01 day ago
    I see the example for running a distributed task queue. The docs aren&#x27;t so clear though for running a distributed workflow, apart from the comment about using a vm id and the admin API.<p>We use spot instances for most things to keep costs down and job queues to link steps. Can you provide an example of a distributed workflow setup?
    • KraftyOne1 day ago
      Got it! What specifically are you looking for? If you launch multiple DBOS instances connected to the same Postgres database, they&#x27;ll automatically form a distributed task queue, dividing new work as it arrives on the queue. If you&#x27;re looking for a lightweight deployment environment, we also have a hosted solution (DBOS Cloud).
  • darkteflon1 day ago
    What is the determinism constraint? I noticed it mentioned several times in blog posts, but one of the use-cases mentioned here is for use with LLMs, which produce non-deterministic outputs.
    • KraftyOne1 day ago
      Great question! A workflow should be deterministic: if called multiple times with the same inputs, it should invoke the same steps with the same inputs in the same order. But steps don&#x27;t have be deterministic, they can invoke LLMs, third party APIs, or any other operation. Docs page on determinism: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;workflow-tutorial#determinism" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;workflow-tutorial...</a>
  • latchkey1 day ago
    Why typeorm over something like <a href="https:&#x2F;&#x2F;mikro-orm.io&#x2F;" rel="nofollow">https:&#x2F;&#x2F;mikro-orm.io&#x2F;</a>?
    • qianli_cs1 day ago
      In addition to TypeORM, DBOS supports several popular ORMs:<p>- Drizzle (we&#x27;re also a sponsor to Drizzle): <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-drizzle" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-drizzl...</a><p>- Knex: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-knex" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-knex</a><p>- Prisma: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-prisma" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;orms&#x2F;using-prisma</a><p>More ORM support is on the way.
      • latchkey1 day ago
        Why not always default to using transactions?
        • qianli_cs1 day ago
          DBOS always uses transactions to perform database operations. If you&#x27;re writing a function that performs database operations, you can use the @DBOS.transaction() decorator to wrap the function so that DBOS&#x27;s bookkeeping records commit in the same transaction as your operation.<p>However, if you&#x27;re interfacing with a third-party API, then that wouldn&#x27;t be part of a database transaction (you&#x27;ll use @DBOS.step instead). The reason is that you don&#x27;t want to hold database locks when you&#x27;re not performing database operations.
  • psadri1 day ago
    Where is the state stored? In my own pg instance? Or is it stored somewhere in the cloud? Also, a small sample code snippet would be helpful.
    • KraftyOne1 day ago
      The state can be stored in any Postgres instance, either locally or in any cloud.<p>For code, here&#x27;s the bare minimum code example for a workflow:<p><pre><code> class Example { @DBOS.step() static async step_one() { ... } @DBOS.step() static async step_two() { ... } @DBOS.workflow() static async workflow() { await Example.step_one() await Example.step_two() } } </code></pre> The steps can be any TypeScript function.<p>Then we have a bunch more examples in our docs: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;</a>.<p>Or if you want to try it yourself download a template:<p><pre><code> npx @dbos-inc&#x2F;create</code></pre>
      • psadri1 day ago
        Are there any constraints around which functions can be turned into steps? I assume their state (arguments?) need to be serializable?<p>Also, what happens with versioning? What if I want to deploy new code?
        • KraftyOne1 day ago
          Yeah, the arguments and return values of steps have to be serializable to JSON.<p>For versioning, each workflow is tagged with the code version that ran it, and we recommend recovering workflows on an executor running the same code version as what the workflow started on. Docs for self hosting: <a href="https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-hosting" rel="nofollow">https:&#x2F;&#x2F;docs.dbos.dev&#x2F;typescript&#x2F;tutorials&#x2F;development&#x2F;self-...</a>. In our hosted service (DBOS Cloud) this is all done automatically.
          • CMCDragonkai1 day ago
            If you were to use cbor, you could support binary values more easily.
  • Loved the Supabase coverage from a month ago, showing under the hood what DBOS is storing &amp; how the data flow works on it. It made real what DBOS was for me, clicked; before DBOS felt very abstract to me.<p><a href="https:&#x2F;&#x2F;supabase.com&#x2F;blog&#x2F;durable-workflows-in-postgres-dbos">https:&#x2F;&#x2F;supabase.com&#x2F;blog&#x2F;durable-workflows-in-postgres-dbos</a> <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42379974">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42379974</a>
  • 5Qn8mNbc2FNCiVV22 hours ago
    Is there a way to use it without decorators?
  • purpleinfs1 day ago
    nice work