Celebal Technologies

OLTP Meets OLAP. May the
Source Be with You: A Lakebase
Story

8 min readSeptember 03, 2026
Lakebase blog thumbnail
Sridhar Pothamsetti

Deputy Vice President Data Engineering,
AI & Architecture

The Two-Database Problem

For years, building an application meant running two databases that had almost nothing to do with each other.

On one side was the operational database - SQL Server, MySQL, Oracle or PostgreSQL. This is where the application lived. A user opens a record, changes a field, saves. The database returns a single row in a few milliseconds and accepts the write immediately. Everything the business was actually doing that day was there.

On the other side was the analytical platform - the lakehouse. Delta tables, a SQL warehouse, dashboards, reports, and increasingly the models. This is where the same data went to be understood: joined with history, aggregated, scanned across years.

Between them sat a pipeline. Every night, or every hour, a job copied data out of the operational database into the lakehouse. Often a second job copied results back the other way, so the application could show a figure the lakehouse had calculated.

So the same data existed in two places, in two formats, on two schedules. Nobody designed that on purpose. It was simply the only way to get low-latency writes and large-scale analytics at the same time.

It also charged rent every month:

Duplication

The same table maintained twice, drifting apart as one side changes and the other does not.

A pipeline to own

Somebody builds it, monitors it, and gets called when it fails at three in the morning.

Data that is always behind

What the application shows is as old as the last successful run.

Two operational estates

To patch, size, back up, secure and pay for.

Paying for peak around the clock

Because a traditional database is sized for its busiest hour and costs the same when it is idle.

The Governance Gap

That is the part which gets the least attention and caused us the most trouble.

The lakehouse side had governance. Unity Catalog knew who each user was, what they were allowed to read, which columns were masked, and where every table had come from. If somebody asked who could see a piece of data, there was one place to look and one answer.

The operational database had none of that. It sat outside the platform entirely, and it showed:

Its own identities

Database logins with no relationship to the company directory or the workspace.

Its own permissions

Grants held inside the database, maintained by hand, and reviewed rarely.

Lineage that stopped at the boundary

You could trace a Delta table back to the pipeline that filled it, and no further.

Two audit trails

one in the platform and one in the database, neither of them complete on its own.

Credentials in files

Because the application had no platform identity to use, its username and password ended up in a configuration file on the web server - frequently in source control, usually shared between people, and almost never rotated.

Put plainly: the freshest and most sensitive data in the company - live customer records, live transactions - sat in the least governed system. The copy downstream of it was the one with the policies attached.

That was the position the industry was in. The lakehouse solved analytics properly, but it never replaced the transactional database - so the split, the pipeline and the governance gap all stayed. Until Lakebase.

How Lakebase Closes the Gap

Lakebase closes the gap rather than bridging it. Instead of the application keeping its database somewhere else, the operational database moves inside Databricks - next to the lakehouse data, and under the same governance.

Figure 1.

Figure 1. The operational database as an object inside the platform. It is listed, created and managed in the workspace alongside everything else, rather than being a separate estate reached across an integration boundary.

Taking the problems above in order:

One platform, not two estates

Databricks manages the database. There is no separate server to patch or size.

No pipeline to build

Moving data between the lakehouse and the operational database is a feature you configure, not a job you write and then maintain.

Fresher data

That synchronisation runs once, on a trigger, or continuously, so you choose how current the figure has to be.

One definition of the table

because the operational copy is fed from the lakehouse rather than kept in step by hand.

One identity model

Databricks users, groups and service principals can authenticate to the database directly, so an application can have an identity instead of a password in a file.

One place to grant and review access

shared with the rest of the platform.

Compute separated from storage

Capacity follows demand and idle compute

Copies in seconds

A branch or clone of the database is a fast operation rather than a restore measured in hours.

And the detail that decides whether any of this is usable on a system that already exists: the application does not have to be rewritten. Lakebase is PostgreSQL, so anything that can already speak to Postgres can speak to Lakebase with the driver it already has.

What Lakebase Is?

Lakebase is a fully managed PostgreSQL database that runs inside the Databricks platform. That sentence is short, and almost everything useful follows from it.

It is genuinely Postgres. It speaks the PostgreSQL wire protocol, which means the driver your application already uses to talk to Postgres connects to Lakebase without modification. There is no Databricks SDK in the data path, no proprietary client library, and no new dialect to learn. An application connects to a host on port 5432, authenticates, and issues SQL. From the application's point of view it is talking to a Postgres server - because it is.

What makes it more than hosted Postgres is where it sits. Underneath, compute is separated from storage: data lives durably on cloud object storage while the database compute runs independently and elastically. Around it, the database is part of the same platform as your lakehouse data - the same governance, the same identities, the same workspace.

Figure 2.

Figure 2. The same database up close. Compute and storage are reported separately, and the database has branches - so a working copy for development is created rather than restored.

The shortest useful definition: Lakebase is the transactional database that lives where your analytical data already is.

The rest of this part is the detail - where Lakebase fits beside what you already run, what its features are, how you connect to it, and which of those features actually earned their keep when the work was real. One number for scale before that: across five production applications, the largest single migration touched 94 files and changed 129 lines. Every one of those lines was the same edit.

Where Lakebase Fits in the Platform

A question most readers form early, and worth answering plainly: Lakebase does not replace the parts of the platform you already use.

ComponentRole
LakebaseTransactional and operational data - the database an application talks to
Delta / lakehouseAnalytical and historical data, at volume
SQL WarehouseThe analytical query engine - unchanged, and not replaced
Unity CatalogOne identity and permission model across both sides

Lakebase also synchronises with lakehouse tables directly, which removes the external pipeline from the picture. How fresh that data needs to be is configurable:

ModeBehaviourUse when
SnapshotFull copy on every run, replaced atomicallyHigh-churn data, or a source without Change Data Feed
TriggeredRefreshes when you run itIncremental changes on a schedule you control (needs Change Data Feed)
ContinuousKeeps data flowing as it changesThe application needs near-real-time data (needs Change Data Feed)

These are complementary planes in one platform rather than competing products. The operational store sits beside the analytical one instead of across an integration boundary from it.

Lakebase Compared with Managed PostgreSQL

If it is just Postgres, the obvious question is why not use Azure Database for PostgreSQL, or Amazon RDS. It is a fair question and it deserves a straight answer.

Governance in one plane

Identity, permissions and auditing are shared with the rest of the platform rather than being a second estate to manage.

Proximity

The transactional store sits next to the analytical one, so synchronising between them is a platform feature rather than a pipeline you build.

Operational surface

One platform, one networking model, one set of credentials, one support relationship.

Core Features

Pulling the above together, along with the capabilities that matter day to day:

FeatureWhat it gives you
PostgreSQL compatibilityExisting drivers, tools, SQL and extensions work unchanged
Serverless elastic computeCapacity follows demand instead of being sized for peak
Scale to zeroIdle compute costs nothing
Separated durable storageLow-cost, effectively unlimited, independent of compute
Branching and instant clonesA working copy of the database in seconds, not hours
Point-in-time recoveryRoll back to a moment rather than to last night's backup
Lakehouse synchronisationSnapshot, triggered or continuous - no external pipeline
Roles and row-level securityStandard Postgres access control, enforced by the database
Extension supportIncluding pgvector, for embedding and search workloads
Standard PostgreSQL toolingpsql, pg_dump and the usual clients work, so moving data out is a standard operation

Every introduction to Lakebase publishes a list like this one. What almost none of them tell you is which entries earn their keep once you are doing real work - so that is the next section.

Figure 3.

Figure 3. Several of the features above on one screen: the compute size, the autosuspend setting that governs whether idle compute scales to nothing, and ordinary PostgreSQL telemetry - connection counts, database size, deadlocks and row activity. Autosuspend is set to never on this database, so it does not scale to zero; that is a setting rather than a property of the service.

The Features That Mattered in Practice

Across the five migrations, four features did the work:

PostgreSQL compatibility

This is the one that made everything else possible. Existing drivers connected unchanged, existing SQL knowledge transferred, and migration became a connectivity exercise rather than a rewrite.

Lakehouse synchronisation

Reference data now arrives in the operational database from the lakehouse without an external pipeline to build and monitor.

Native Postgres roles with passwords

Applications that read their credentials from a configuration file at startup could connect with no code change at all.

Serverless compute and scale to zero

Capacity follows demand rather than being provisioned for the worst hour of the month, and idle compute costs nothing.

Connecting to Lakebase

An application needs five things: a host, port 5432, a database name, credentials, and SSL enabled. Encryption is not optional, so plan for it rather than discovering it.

Whatever your application is written in, it connects with that language's standard Postgres driver:

StackDriverConnection form
PerlDBD::Pgdbi:Pg:host=...;port=5432;dbname=...;sslmode=require
Perl / ODBCpsqlODBCDRIVER={PostgreSQL Unicode(x64)};SERVER=...;SSLmode=require
.NETNpgsqlHost=...;Port=5432;Database=...;SSL Mode=Require
Pythonpsycopg2 / psycopg3postgresql://host:5432/db?sslmode=require
JavaPostgreSQL JDBCjdbc:postgresql://host:5432/db?sslmode=require

That table is the whole compatibility argument in practice. Three of those drivers were used across the five applications, none of them written with Databricks in mind, and none of them needed changing.

One setting worth knowing before you start: the search path. If your queries reference tables without schema-qualifying them, setting the search path in the connection string lets those names resolve to the schema you migrated into - so the queries themselves never change. On a large legacy codebase this single setting removes an enormous amount of mechanical editing.

Host=<instance>.database.<region>.cloud.databricks.com;Port=5432;

Database=<database>;Username=<role>;Password=<password>;

SSL Mode=Require;Search Path=<schema>

Authentication Options

This is the decision that interacts most with how your application is built, and the platform's own defaults tell you which method it considers the norm.

Figure 4.

Figure 4. Connection types are configured per database project. OAuth is permanently enabled; password authentication is an explicit opt-in.

OAuth authentication - Databricks users, groups and service principals connecting with a Databricks token - is always on and cannot be switched off. Authentication with a native Postgres role and a static password is a checkbox somebody has to deliberately tick. That asymmetry is worth reading as guidance: identity-based access is the model the platform expects, and static passwords are a supported exception rather than the standard route.

Option A: A Native PostgreSQL Role with a Password

This is the familiar model: a role inside the database, a password, and a connection string any Postgres driver understands. Enabling it takes two steps - password authentication has to be allowed for the database project at all, and then the role itself is created from the Roles and Databases tab.

Figure 5.

Figure 5. Creating a native Postgres role. The authentication type is fixed at creation, and the password is generated by the platform rather than chosen.

Two details there matter more than they first appear. The authentication type - OAuth or Password - is chosen when the role is created, so it is a property of the role rather than something toggled later. And the password is generated automatically and held in a secure vault rather than typed in, which quietly removes the most common way static credentials go wrong: somebody choosing a weak one and reusing it elsewhere.

Treat the system roles and attributes conservatively. Granting superuser gives the role read and write access to all data, and the create-database, create-role and bypass-row-level-security attributes each widen what it can do. An application that reads and writes its own tables needs none of them.

Figure 6.

Figure 6. The generated connection string. Note the role selector, the password reset action, and the connection pooling toggle.

The connection string is an ordinary Postgres URI - role, password, host, database and sslmode. Nothing in it is specific to Databricks except the hostname, which is precisely why an existing driver connects to it unmodified. Three things on that dialog are easy to overlook and useful later: the role selector regenerates the string per role so each application can be issued its own, the reset action rotates a credential without recreating the role, and the connection pooling toggle matters for anything with a per-request connection model.

Option B: A Databricks Identity with an OAuth Token

The second method authenticates as a Databricks identity - a user, a group, or, for an application, a service principal. It needs no enabling because it is always available.

The mechanism is neat: the identity generates a short-lived OAuth token, and that token is supplied in the password field of an otherwise ordinary Postgres connection. The driver neither knows nor cares that the password is a token, which is why this works with exactly the same unmodified drivers as Option A.

The security posture is considerably better. The application has an identity rather than a secret. Access is granted and revoked in the same place as every other permission. There is no long-lived credential in a file to leak or forget about, and the audit trail leads back to a named principal instead of a shared database role.

The catch is lifetime. These tokens are short-lived - on the order of an hour - so the application needs somewhere to refresh them. If your code reads a connection string from configuration at startup and holds it, that connection will begin failing authentication about an hour after deployment.

Figure 7.

Figure 7. Authenticating as a Databricks identity. The token is short-lived, and it is supplied in the password field of an otherwise ordinary Postgres connection.

Comparing the Two Options

ConsiderationNative role + passwordDatabricks identity + OAuth token
AvailabilityOpt-in per database projectAlways enabled
CredentialAuto-generated, held in a vaultShort-lived OAuth token
LifetimeUntil explicitly rotatedAround an hour
Refresh logic neededNoYes
RevocationReset the role's passwordCentral, with the identity
Audit trailA shared database roleA named identity
Driver supportAny Postgres driverAny Postgres driver
Best suited toLegacy apps reading config at startupServices with a connection layer

What Comes Next in This Series

That is the theory. The rest of this series is the practice - one application per part, each with the code that changed, the architecture before and after, and screenshots of the application running against both databases.

Part 2 takes the first of the applications: a Perl CGI tool moving from SQL Server to Lakebase. It covers the architecture before and after, how the application connects to each database, what actually changed between the two builds, and the application running against both. Parts 3 to 6 follow the same shape, one application each, ending with a new application built directly on Lakebase.