DBOS provides lightweight sustainable workflows built on top of Postgres. Essentially, it helps you write long-running, reliable code that can survive crashes, restarts, and failures without losing state or duplicating work.
As your workflow runs, DBOS checks each step taken in the Postgres database. When a process stops (fails, is intentionally suspended, or the machine shuts down), your program can recover from those checkpoints to restore its exact state and continue where it left off, as if nothing happened.
In practice, this makes it easier to build reliable systems for use cases like AI agents, data synchronization, payments, or anything else that takes minutes, days, or weeks to complete. Instead of emphasizing ad-hoc retry logic and database checkpoints, the DBOS workflow gives you a consistent model to ensure that your programs can recover from any failure exactly where they left off.
This library includes everything you need to add sustainable workflows to your program: no separate services or orchestrators or any external dependencies except Postgres. Because it’s just a library, you can add it to your projects sequentially, and it works out of the box with frameworks like Spring. And because it’s built on Postgres, it supports basically all the tooling you’re familiar with (backups, GUI, CLI tools) and works with any Postgres provider.
💾 Sustainable Workflows
Workflows create your program durable By checking its status in Postgres. If your program ever fails, all your workflows will automatically resume from the last completed step when it restarts.
You add sustainable workflows to your existing Java program in a few lines of code by registering common tasks as workflows and steps:
interface Example {
public void workflow();
}
class ExampleImpl implements Example {
private void stepOne() {
System.out.println("Step one completed!");
}
private void stepTwo() {
System.out.println("Step two completed!");
}
@Workflow()
public void workflow() {
DBOS.runStep(() -> stepOne(), "stepOne");
DBOS.runStep(() -> stepTwo(), "stepTwo");
}
}Workflows are particularly useful
- Streamlining business processes so that they can recover seamlessly from any failure.
- Building observable and fault-tolerant data pipelines.
- Operating an AI agent, or any application that relies on unreliable or non-deterministic APIs.
read more
📒 Asynchronous execution
You can run your workflows asynchronously without making any changes to their interface or implementation.
This is ideal for long-running background workflows: you can come back to the code later and check the completion status and/or get the results.
var handle = DBOS.startWorkflow(()->example.exampleWorkflow("HelloDBOS"));
result = handle.getResult();read more
📒 Sustainable queues
DBOS queues help you durable Run distributed tasks. You can list a task from a sustainable workflow and one of your processes will pick it up for execution. DBoS manages the execution of your tasks: it guarantees that tasks complete, and that their callers get their results without needing to resubmit them, even if your application is interrupted.
Queues also provide flow control, allowing you to limit the concurrency of your tasks on a per-queue or per-process basis. You can also set timeouts for tasks, set a rate limit on how often queued tasks are executed, duplicate tasks, or prioritize tasks.
You can add queues to your workflow in just a few lines of code. They don’t need a separate queue service or message broker – just Postgres.
public void queuedTasks() {
for (int i = 0; i < 3; i++) {
String workflowId = "child" + i;
var options = new StartWorkflowOptions(workflowId).withQueue(q);
List<WorkflowHandle<String>> handles = new ArrayList<>();
handles.add(DBOS.startWorkflow(()->simpleService.childWorkflow(workflowId), options));
}
for (int i = 0 ; i < 3 ; i++) {
String workflowId = "child"+i;
var h = DBOS.retrieveWorkflow(workflowId);
System.out.println(h.getResult());
}
}
// In your main
var queue = new Queue("exampleQueue");
DBOS.registerQueue(queue);read more
📅 Sustainable scheduling
Schedule a workflow using the cron syntax, or use durable sleep to pause the workflow for as long as you want (even days or weeks) before execution.
You can schedule a workflow using a single annotation:
public class SchedulerImpl implements Scheduler {
@Workflow(name = "every5Second")
@Scheduled(cron = "0/5 * * * * ?")
public void every5Second(Instant schedule , Instant actual) {
log.info("Executed workflow "+ schedule.toString() + " " + actual.toString()) ;
}
}
// In your main
DBOS.registerWorkflows(Scheduler.class, new SchedulerImpl());read more
📫 Sustainable notifications
Pause your workflow execution until you receive a notification, or emit events from your workflow to send progress updates to an external client. All information is stored in Postgres, so that they can be sent and received with exactly-once semantics. Set durable timeouts while waiting for events, so you can wait as long as you want (days or even weeks) through interruptions or restarts, then resume when a notification arrives or the timeout is complete.
For example, create a reliable billing workflow that waits for notification from the payment service, processing it exactly once:
@Workflow(name = "billing")
public void billingWorkflow() {
// Calculate the charge, then submit the bill to a payments service
String paymentStatus = (String) DBOS.recv(PAYMENT_STATUS, paymentServiceTimeout);
if (paymentStatus.equals("paid")) {
// handle paid
} else {
// handle not paid
}
}
@Workflow(name = "payment")
public void payment(String targetWorkflowId) {
DBOS.send(targetWorkflowId, PAYMENT_STATUS, "paid") ;
}
To get started, follow the quickstart to install this open-source library and connect it to a Postgres database. Then, check out the programming guide to learn how to build with sustainable workflows and queues.
https://docs.dbos.dev
https://docs.dbos.dev/examples
dbos vs temporal
Both dBoS and temporal provide durable execution, but dBoS is implemented in a lightweight Postgres-supported library while temporal is implemented in an externally orchestrated server.
You can add DBOS to your program by installing the open-source library, connecting it to Postgres, and annotating the workflow and steps. In contrast, to add temporal to your program, you must reorganize your program to move your workflows and steps (activities) to the temporal worker, configure the temporal server to host those workflows, and access your workflow only through the temporal client. This page compares in more detail.
If you want to ask questions or hang out with the community, join us on Discord! If you spot a bug or have a feature request, don’t hesitate to open an issue here on GitHub. If you’re interested in contributing, check out our contribution guide.
