✨ From vibe coding to vibe deployment. UBOS MCP turns ideas into infra with one message.

Learn more
Andrii Bidochko
  • Updated: February 19, 2026
  • 8 min read

Oban Enables Seamless Elixir‑Python Integration for Background Jobs



Bridging Elixir and Python with Oban: A Developer’s Guide

Discover how Oban enables seamless cross‑language background job processing between Elixir and Python, with a step‑by‑step Badge Forge demo, best‑practice tips, and real‑world benefits for modern SaaS teams.

Answer: Oban acts as a shared PostgreSQL‑backed job queue that lets Elixir and Python applications enqueue, process, and monitor jobs from a single table, making cross‑language integration simple, reliable, and fully observable.

Why Bridge Elixir and Python?

Many software teams face a classic dilemma: the core of their system is built in Elixir for its concurrency and fault‑tolerance, yet critical libraries—such as machine‑learning models, PDF rendering, or audio processing—are only mature in Python. Re‑writing these capabilities in Elixir can be costly and risky. Instead, a durable job queue that both runtimes understand lets you keep each language where it shines.

UBOS homepage showcases how modern platforms combine the best of multiple ecosystems. By leveraging Oban, you can adopt the same philosophy: let Elixir handle high‑throughput web traffic while Python tackles specialized tasks like PDF generation with WeasyPrint.

Oban: The Job Queue That Speaks Both Languages

Oban is an open‑source, PostgreSQL‑backed background‑job processor for Elixir. Its design revolves around a single oban_jobs table where each row represents a job, its arguments (stored as JSON), and its execution state. The same table can be accessed by a Python client—OpenAI ChatGPT integration—that reads and writes jobs using the same schema.

Key features that make Oban ideal for cross‑language bridging:

  • Transactional inserts guarantee exactly‑once delivery.
  • Built‑in retries, back‑off, and dead‑letter queues.
  • Real‑time PubSub notifications via PostgreSQL LISTEN/NOTIFY.
  • Web UI (Oban Web) for monitoring from any language.

How Oban Bridges Elixir and Python

The bridge works because both runtimes treat the oban_jobs table as the single source of truth. An Elixir process enqueues a job by inserting a row; a Python worker polls the same table, claims the job, processes it, and updates the status. No additional message broker (RabbitMQ, Kafka) is required.

Shared Database – The Core of Interop

Sharing a PostgreSQL instance may feel daring, but it’s the same database you already use for your application data. Oban’s schema is deliberately lightweight, so the impact on existing tables is minimal. Both sides maintain independent leader election, meaning an Elixir node never competes with a Python process for “master” duties.

Job Payloads as JSON

Because arguments are JSON, any serializable data structure works across languages. For example, a badge‑generation request can include {"id":"","name":"Alice","company":"Acme Corp","type":"speaker"}. Python reads this payload directly into a dictionary, while Elixir receives a map.

Two‑Way Communication

After a Python worker finishes its task, it can enqueue a follow‑up job back to the Elixir side (e.g., a “print” job). This pattern creates a full duplex pipeline without any custom RPC layer.

Badge Forge Demo: From Enqueue to PDF

Let’s walk through a concrete example called Badge Forge. The goal is simple: generate conference badges as PDFs using Python’s WeasyPrint, while the orchestration lives in an Elixir app.

Step 1 – Enqueue Jobs in Elixir


def enqueue_batch(count \\ 100) do
  generate = fn _ ->
    args = %{
      id: Ecto.UUID.generate(),
      name: Faker.Person.name(),
      company: Faker.Company.name(),
      type: Enum.random(~w(attendee speaker sponsor organizer))
    }

    Oban.Job.new(args,
      worker: "badge_forge.generator.GenerateBadge",
      queue: :badges
    )
  end

  1..count
  |> Enum.map(generate)
  |> Oban.insert_all()
end

The worker field is a string that matches the fully‑qualified Python class name, enabling the Python side to recognize the job.

Step 2 – Python Worker Consumes the Job


from oban import Job, Oban, worker
from weasyprint import HTML

@worker(max_attempts=5, queue="badges")
class GenerateBadge:
    async def process(self, job: Job) -> None:
        badge_id = job.args["id"]
        name = job.args["name"]
        company = job.args["company"]
        role = job.args["type"]

        html = render_badge_html(name, company, role)
        path = BADGES_DIR / f"{badge_id}.pdf"
        HTML(string=html).write_pdf(str(path))

        # Enqueue a confirmation job back to Elixir
        confirmation = Job(
            args={"id": badge_id, "name": name, "path": str(path)},
            queue="printing",
            worker="BadgeForge.PrintCenter"
        )
        await Oban.get_instance().enqueue(confirmation)

Step 3 – Elixir Prints the Result


defmodule BadgeForge.PrintCenter do
  use Oban.Worker, queue: :printing
  require Logger

  @impl Oban.Worker
  def perform(%Oban.Job{args: %{"id" => id, "name" => name, "path" => path}}) do
    Logger.info("Printing badge #{id} for #{name}: #{path}")
    # Insert actual printing logic here
    :ok
  end
end

Step 4 – Visual Monitoring with Oban Web

Run the official Docker image to get a live dashboard:


docker run -d \
  -e DATABASE_URL="postgres://user:pass@host:5432/badge_forge_dev" \
  -p 4000:4000 \
  ghcr.io/oban-bg/oban-dash

Navigate to http://localhost:4000 to watch jobs flow from Elixir to Python and back. The UI shows retries, latency, and success rates—all without writing a single line of front‑end code.

Benefits of Using Oban for Cross‑Language Jobs

  • Reliability: PostgreSQL guarantees durability; jobs survive crashes and restarts.
  • Observability: One dashboard (Oban Web) visualizes activity from both runtimes.
  • Scalability: Horizontal scaling works independently for each language; add more Python workers without touching Elixir.
  • Language‑agnostic payloads: JSON arguments let you evolve schemas without breaking the other side.
  • Zero additional infra: No need for RabbitMQ, Redis, or external brokers.

Best‑Practice Checklist

  1. Version‑lock the schema: Keep the oban_jobs migration in sync across both codebases.
  2. Namespace queues: Use distinct queue names (e.g., :badges, :printing) to avoid accidental job stealing.
  3. Idempotent workers: Design both Elixir and Python workers to be safe to retry.
  4. Monitor latency: Set alerts on job age in Oban Web; long‑running PDF generation may need a dedicated worker pool.
  5. Secure DB credentials: Store connection strings in environment variables; never hard‑code them.

Leveraging UBOS for End‑to‑End Automation

While Oban handles the job queue, the UBOS platform overview provides a low‑code environment to stitch together the surrounding services—API gateways, authentication, and UI components—without writing boilerplate.

For instance, you can expose a REST endpoint that triggers enqueue_batch/1 directly from a Web app editor on UBOS. Combine it with the Workflow automation studio to orchestrate downstream notifications (Slack, email) once a badge is printed.

Ready‑Made Templates to Accelerate Your Project

UBOS’s marketplace offers dozens of AI‑powered templates that can be dropped into your Badge Forge pipeline:

These templates illustrate how UBOS’s Enterprise AI platform by UBOS can complement Oban’s job queue, delivering a full‑stack solution from data ingestion to final output.

SEO Meta Description & Target Keywords

Meta description: Learn how to bridge Elixir and Python using Oban’s PostgreSQL‑backed job queue, with a hands‑on Badge Forge demo, best practices, and integration tips for UBOS’s low‑code platform.

Primary keywords: Oban, Elixir, Python integration, background jobs, cross‑language bridging, job queue, Oban Web, WeasyPrint.

Start Building Your Cross‑Language Pipeline Today

Ready to replace fragile HTTP bridges with a robust, observable job queue? Explore the UBOS pricing plans to find a tier that includes the Workflow Automation Studio and access to the Template Marketplace. Then clone the Badge Forge repo, point both services at a shared PostgreSQL instance, and watch Oban do the heavy lifting.

Have questions or want a live walkthrough? Join the community on the About UBOS page and reach out to our support engineers. Together we’ll turn your multi‑language vision into production‑ready reality.

Diagram of Oban bridging Elixir and Python

For startups looking to prototype quickly, check out UBOS for startups. Small and medium businesses can benefit from UBOS solutions for SMBs. If you need inspiration, browse the UBOS portfolio examples and see how other teams have combined AI agents and job queues.

Want to experiment with AI agents that can trigger Oban jobs? Our AI marketing agents can post‑process badge data, generate social media snippets, and feed them back into the queue for analytics.

Explore more templates that complement your workflow:

Dive in, experiment, and let Oban be the glue that unites your Elixir and Python worlds—while UBOS supplies the low‑code scaffolding that turns prototypes into production‑grade services.


Andrii Bidochko

CTO UBOS

Andrii Bidochko is an AI entrepreneur and researcher focused on AI agents, reinforcement learning, and autonomous systems. He writes about the technologies shaping the future of machine intelligence, from frontier models and agent architectures to real-world AI applications.

Sign up for our newsletter

Stay up to date with the roadmap progress, announcements and exclusive discounts feel free to sign up with your email.

Sign In

Register

Reset Password

Please enter your username or email address, you will receive a link to create a new password via email.