<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: daun-gatal</title>
    <description>The latest articles on DEV Community by daun-gatal (@daungatal).</description>
    <link>https://dev.to/daungatal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3708126%2Fdfd23570-8a5f-4ecb-ae7c-7189a34c3bd9.jpeg</url>
      <title>DEV Community: daun-gatal</title>
      <link>https://dev.to/daungatal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daungatal"/>
    <language>en</language>
    <item>
      <title>I Love Debezium Server. Operating It Was Another Story, So I Built BeziSync</title>
      <dc:creator>daun-gatal</dc:creator>
      <pubDate>Sun, 01 Nov 2026 02:00:09 +0000</pubDate>
      <link>https://dev.to/daungatal/i-love-debezium-server-operating-it-was-another-story-so-i-built-bezisync-2473</link>
      <guid>https://dev.to/daungatal/i-love-debezium-server-operating-it-was-another-story-so-i-built-bezisync-2473</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Debezium Server is a great way to do change data capture without running Kafka Connect, but operating it in production is painful. I built &lt;a href="https://bezisync.dglabs-ai.dev" rel="noopener noreferrer"&gt;BeziSync&lt;/a&gt;, a web UI and control plane that checks your database before you deploy, protects the source, turns operations into buttons, and only shows green when there's proof. There's a playground you can sign in to with Google.&lt;/p&gt;




&lt;p&gt;The first time I got Debezium Server running, I was honestly a bit surprised. One container, one properties file, and rows from Postgres were showing up in Kafka a few seconds after I inserted them. No Kafka Connect cluster to babysit. No plugin folders. It just worked.&lt;/p&gt;

&lt;p&gt;The second time was less fun. A pipeline had been stopped for a weekend, nobody noticed, and on Monday the replication slot was holding a lot more WAL than anyone was comfortable with. The disk alert on the database got to us before any alert about the pipeline did.&lt;/p&gt;

&lt;p&gt;That gap between "it works on my laptop" and "I trust this in production" is what this post is about. It's also why I ended up building BeziSync.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debezium Server, quickly
&lt;/h2&gt;

&lt;p&gt;If you haven't used it: &lt;a href="https://debezium.io/" rel="noopener noreferrer"&gt;Debezium&lt;/a&gt; reads the transaction log of your database (the WAL in Postgres, the binlog in MySQL, the oplog in MongoDB) and turns every insert, update and delete into an event. That's change data capture, or CDC.&lt;/p&gt;

&lt;p&gt;Most people meet Debezium as a set of Kafka Connect plugins. &lt;a href="https://debezium.io/documentation/reference/stable/operations/debezium-server.html" rel="noopener noreferrer"&gt;Debezium Server&lt;/a&gt; is the other way to run it. It's a standalone app that runs one connector and sends events straight to a sink: Kafka, Pub/Sub, Kinesis, Redis Streams, NATS, HTTP, and more.&lt;/p&gt;

&lt;p&gt;A minimal setup looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;debezium.source.connector.class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;io.debezium.connector.postgresql.PostgresConnector&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.database.hostname&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;shop-db&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.database.user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;debezium&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.database.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.plugin.name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pgoutput&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.topic.prefix&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;shop&lt;/span&gt;
&lt;span class="py"&gt;debezium.source.table.include.list&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;public.orders&lt;/span&gt;
&lt;span class="py"&gt;debezium.sink.type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;kafka&lt;/span&gt;
&lt;span class="py"&gt;debezium.sink.kafka.producer.bootstrap.servers&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;kafka:9092&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a lot of teams that's a much better deal. You don't need Kafka just to move data from Postgres into a lakehouse. You run one small process per pipeline and you're done.&lt;/p&gt;

&lt;p&gt;At least, that's how it feels on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it starts to hurt
&lt;/h2&gt;

&lt;p&gt;Debezium Server is simple to start. It is not simple to operate. After running it for a while, these were the things that kept coming back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The database has to be set up just right.&lt;/strong&gt; &lt;code&gt;wal_level=logical&lt;/code&gt;, a user with replication rights, a publication, the right binlog format, &lt;code&gt;REPLICA IDENTITY&lt;/code&gt; on tables without keys. Every cloud does it differently. RDS has parameter groups, Cloud SQL has flags, Azure has its own thing. You usually find out what's missing when the connector crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A stopped pipeline can hurt the source.&lt;/strong&gt; A Postgres replication slot keeps WAL until the consumer reads it. If the connector is down, that WAL piles up. Leave it long enough and you're in trouble.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything is a properties file.&lt;/strong&gt; Snapshots, offsets, transforms, sink settings. All of it is &lt;code&gt;debezium.source.*&lt;/code&gt; and &lt;code&gt;debezium.sink.*&lt;/code&gt; keys. One typo and you're reading Java stack traces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Running" doesn't mean "working".&lt;/strong&gt; The container is up, the health endpoint says UP, and no events have arrived for an hour. Which one do you believe?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple operations aren't simple.&lt;/strong&gt; Re-snapshot one table. Reset the offset. Roll back yesterday's config change. Each one is a small research project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It doesn't scale to people.&lt;/strong&gt; In practice one or two engineers end up as "the Debezium people", and everyone else files a ticket and waits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is Debezium's fault, really. It's a great engine. What's missing is the layer around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I built BeziSync
&lt;/h2&gt;

&lt;p&gt;BeziSync is a web UI and control plane for Debezium Server. The idea is easy to say: someone who knows the platform sets things up once, and after that any engineer can create and run CDC pipelines without becoming a Debezium expert first.&lt;/p&gt;

&lt;p&gt;An admin connects a runtime (a Kubernetes namespace or a Docker host) and sets the guardrails. Then anyone on the team can go through a short wizard: pick a source database, pick the tables, pick a destination, review, deploy. BeziSync writes the &lt;code&gt;application.properties&lt;/code&gt;, starts one Debezium Server per pipeline, and keeps an eye on it from then on.&lt;/p&gt;

&lt;p&gt;Right now it works with PostgreSQL, MySQL/MariaDB, SQL Server and MongoDB as sources. For destinations: Kafka, Apache Iceberg (REST catalogs, AWS Glue, S3 Tables), JDBC databases, Pub/Sub, Kinesis, SQS, SNS, Event Hubs, Pulsar, Redis Streams, NATS and HTTP.&lt;/p&gt;

&lt;p&gt;You can still see the generated config at any point. I didn't want to hide Debezium. I just didn't want everyone to have to type it by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does about each of those problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Checks before anything deploys
&lt;/h3&gt;

&lt;p&gt;When you add a source, BeziSync checks it the way Debezium will use it: logical replication, privileges, retention, primary keys, TLS, network access (including through an SSH bastion). There are more than 150 checks right now. When one fails, it doesn't just say "failed". It shows the exact fix for where your database runs, whether that's self-hosted, RDS, Cloud SQL or Azure. There's even a "send to my DBA" message you can copy, because often you're not the one who can change &lt;code&gt;wal_level&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same goes for the pipeline itself. If a transform would make Debezium stop with a duplicate field name, the deploy is blocked before it happens. You don't find out from the logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protecting the source database
&lt;/h3&gt;

&lt;p&gt;Every pipeline page shows what the pipeline is costing the source, in that database's own terms. For Postgres, that's the replication slot, how much WAL it's holding, and how much room is left before &lt;code&gt;max_slot_wal_keep_size&lt;/code&gt; drops it. For MySQL, the binlog file being read and whether the next purge would remove it. For MongoDB, the oplog window. For SQL Server, the CDC retention.&lt;/p&gt;

&lt;p&gt;There's a default limit on how much log a pipeline may hold, an alert when it gets close, and maintenance windows so big snapshots run at night instead of at peak time. That's the weekend story from the start of this post, handled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations are buttons
&lt;/h3&gt;

&lt;p&gt;Pause, resume, restart. Re-snapshot a few tables while streaming keeps going. See the stored offset, or reset it, with a typed confirmation. Every saved change is a version, so rolling back is choosing an older version and deploying it. Before you confirm, BeziSync tells you what will happen: whether the connector restarts, what changes for consumers, and whether someone needs to approve it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Health you can believe
&lt;/h3&gt;

&lt;p&gt;This one matters to me most. A pipeline is green only when there's fresh evidence that it's working. If BeziSync can't measure something, it says Unknown and shows it in grey, never green. There's also an optional delivery canary: every few minutes it writes a tiny row on the source, looks for it at the destination, and tells you "verified 2 minutes ago, 4 s end to end". If the row doesn't show up, you get an alert. That's how you catch "the container is up but nothing is moving".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhtcor5kdiypck8d9hg4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhtcor5kdiypck8d9hg4j.png" alt="A pipeline's Overview page in BeziSync: source protection, throughput and a verified delivery canary" width="800" height="691"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also watches the schema of the tables you capture. A dropped column or a type change is flagged as breaking before your consumers notice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safe for a whole team
&lt;/h3&gt;

&lt;p&gt;Secrets are encrypted and write-only. Once you save a password, nobody can read it back through the UI or the API. There are roles per project (viewer, operator, editor), approvals for production changes, policies, an audit log, SSO, and alerts to Slack, PagerDuty, webhooks or email. If you prefer code over clicking, pipelines can be exported as YAML and managed from a CLI in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it fits together
&lt;/h2&gt;

&lt;p&gt;Under the hood it's still plain Debezium Server. BeziSync doesn't fork it or patch it. It just runs it for you, one instance per pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz9jwx48do7uibn1rwflk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz9jwx48do7uibn1rwflk.png" alt="How BeziSync fits around Debezium Server" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The controller deploys each pipeline to a runtime you've connected: a Kubernetes namespace, a Docker host, or a remote cluster through a small agent that only makes outbound connections, so you don't have to open your network. Offsets and schema history live in Postgres, so a pipeline can move or restart without losing its place. There's no extra queue or broker to run either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it and tell me what's wrong
&lt;/h2&gt;

&lt;p&gt;BeziSync is still early, and I'd rather shape it with real users than guess. There's a playground you can sign in to with a Google account: &lt;a href="https://bezisync.dglabs-ai.dev" rel="noopener noreferrer"&gt;bezisync.dglabs-ai.dev&lt;/a&gt;. It already has sample databases with live traffic, Kafka and other sinks, and runtimes on both Kubernetes and Docker. You can build a pipeline end to end in a few minutes, break things, and see what BeziSync tells you.&lt;/p&gt;

&lt;p&gt;What I'd love to hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where you got stuck, or where the UI said something that didn't make sense.&lt;/li&gt;
&lt;li&gt;Which source or destination you'd need that isn't there.&lt;/li&gt;
&lt;li&gt;Whether your team would actually use something like this, and what would stop you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a feedback button inside the app, or drop a comment below. And if you've been the "Debezium person" on your team, I'd really like to hear your war stories.&lt;/p&gt;

</description>
      <category>debezium</category>
      <category>changedatacapture</category>
      <category>debeziumserver</category>
      <category>lakehouse</category>
    </item>
    <item>
      <title>Introducing CHouse UI: A Web Interface for ClickHouse with Built-in RBAC</title>
      <dc:creator>daun-gatal</dc:creator>
      <pubDate>Tue, 13 Jan 2026 12:29:50 +0000</pubDate>
      <link>https://dev.to/daungatal/introducing-chouse-ui-a-web-interface-for-clickhouse-with-built-in-rbac-118b</link>
      <guid>https://dev.to/daungatal/introducing-chouse-ui-a-web-interface-for-clickhouse-with-built-in-rbac-118b</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;ClickHouse is great for analytics, but managing it in a team environment comes with unique challenges. Teams need secure credential management, access control, and audit trails.&lt;/p&gt;

&lt;p&gt;When you’re working with multiple ClickHouse servers across different environments, credentials need to be managed securely. Access control needs to be centralized and consistent. And you need visibility into who ran what query and when.&lt;/p&gt;

&lt;p&gt;We built CHouse UI to address these team management needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What CHouse UI Does
&lt;/h2&gt;

&lt;p&gt;CHouse UI is a web interface for ClickHouse that adds security and access control on top of the database. The key difference is that credentials never leave your server — they’re encrypted and stored server-side, and all connections go through a secure backend proxy.&lt;/p&gt;

&lt;p&gt;This means you can give team members access to CHouse UI without exposing ClickHouse credentials. You can rotate credentials without updating everyone’s configuration. And you have a single place to manage who can access what.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security and Access Control
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Server-Side Credential Storage&lt;/strong&gt;: All ClickHouse credentials are encrypted and stored in a separate RBAC database. The browser never sees them. This architecture lets you safely share access without credential leakage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role-Based Access Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CHouse UI includes six role levels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Super Admin — Full system access&lt;/li&gt;
&lt;li&gt;Admin — User and connection management&lt;/li&gt;
&lt;li&gt;Developer — Write access (INSERT, UPDATE, DDL)&lt;/li&gt;
&lt;li&gt;Analyst — Read access with export&lt;/li&gt;
&lt;li&gt;Viewer — Read-only queries&lt;/li&gt;
&lt;li&gt;Guest — Limited read-only access&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also set granular data access rules. Allow analysts to access analytics databases but deny system tables. Give specific users access to individual tables. Use regex patterns for complex scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Connection Support&lt;/strong&gt;: Manage multiple ClickHouse servers from one interface. Switch between development, staging, production, and analytics clusters with a dropdown. Each connection maintains its own security context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit Logging&lt;/strong&gt;: For compliance and debugging, CHouse UI logs everything: every query, every login, every permission check, every configuration change. All with user context and timestamps. The logs are searchable, filterable, and exportable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: Security shouldn’t come at the cost of usability. CHouse UI uses Monaco Editor for SQL editing, with syntax highlighting. The interface is modern, responsive, and fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features include&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saved queries that persist across sessions&lt;/li&gt;
&lt;li&gt;Searchable query history&lt;/li&gt;
&lt;li&gt;Data export in CSV, JSON, and TSV formats&lt;/li&gt;
&lt;li&gt;Real-time metrics dashboard&lt;/li&gt;
&lt;li&gt;Database explorer with schema inspection&lt;/li&gt;
&lt;li&gt;Table management (create, alter, drop)&lt;/li&gt;
&lt;li&gt;File upload to tables&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Multi-Environment Management&lt;/strong&gt;: A data engineering team manages five ClickHouse clusters (dev, staging, prod, analytics, reporting) through one interface. RBAC ensures developers can’t accidentally modify production data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-Service Analytics&lt;/strong&gt;: Companies enable business analysts to query ClickHouse without direct database access. Analysts get a user-friendly interface with read-only permissions, and every action is logged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;CHouse UI is now publicly available and ready to use:&lt;/p&gt;

&lt;p&gt;🌐 Website: &lt;a href="https://chouse-ui.com" rel="noopener noreferrer"&gt;https://chouse-ui.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 GitHub: &lt;a href="https://github.com/daun-gatal/chouse-ui" rel="noopener noreferrer"&gt;https://github.com/daun-gatal/chouse-ui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get started quickly with Docker, or set it up for production with PostgreSQL. The documentation includes setup guides and configuration options.&lt;/p&gt;

&lt;p&gt;If you’re working with ClickHouse in a team environment and need better security and access control, give CHouse UI a try. We’d love to hear your feedback and see how you’re using it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;CHouse UI is open source and licensed under Apache License 2.0.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>clickhouse</category>
      <category>clickhouseui</category>
    </item>
  </channel>
</rss>
