<?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: Maqbool Thoufeeq T</title>
    <description>The latest articles on DEV Community by Maqbool Thoufeeq T (@maqboolthoufeeq).</description>
    <link>https://dev.to/maqboolthoufeeq</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F805087%2F181da4b7-f103-406d-bf40-b03d75879e41.jpeg</url>
      <title>DEV Community: Maqbool Thoufeeq T</title>
      <link>https://dev.to/maqboolthoufeeq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maqboolthoufeeq"/>
    <language>en</language>
    <item>
      <title>🚀Claude Sub-Agents - The npm for AI developers! (sub-agents CLI)</title>
      <dc:creator>Maqbool Thoufeeq T</dc:creator>
      <pubDate>Fri, 01 Aug 2025 23:23:34 +0000</pubDate>
      <link>https://dev.to/maqboolthoufeeq/claude-sub-agents-the-npm-for-ai-developers-sub-agents-cli-1pil</link>
      <guid>https://dev.to/maqboolthoufeeq/claude-sub-agents-the-npm-for-ai-developers-sub-agents-cli-1pil</guid>
      <description>&lt;p&gt;Specialized &lt;strong&gt;AI agents for your tech stack + Serena integration&lt;/strong&gt; for semantic code analysis.&lt;br&gt;
Try it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx sub-agents init --interactive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Checkout:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/maqboolthoufeeq/sub-agents" rel="noopener noreferrer"&gt;https://github.com/maqboolthoufeeq/sub-agents&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fmjrbjp9l7jk6qs3zijuq.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.amazonaws.com%2Fuploads%2Farticles%2Fmjrbjp9l7jk6qs3zijuq.png" alt=" " width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🤖 Sub-Agents is now open source! Specialized AI agents for your tech stack + Serena integration for semantic code analysis. 👉 https://github.com/maqboolthoufeeq/sub-agents</title>
      <dc:creator>Maqbool Thoufeeq T</dc:creator>
      <pubDate>Fri, 01 Aug 2025 23:18:38 +0000</pubDate>
      <link>https://dev.to/maqboolthoufeeq/sub-agents-is-now-open-source-specialized-ai-agents-for-your-tech-stack-serena-integration-2bo2</link>
      <guid>https://dev.to/maqboolthoufeeq/sub-agents-is-now-open-source-specialized-ai-agents-for-your-tech-stack-serena-integration-2bo2</guid>
      <description></description>
      <category>ai</category>
      <category>opensource</category>
      <category>software</category>
      <category>integrations</category>
    </item>
    <item>
      <title>Change Data Capture (CDC) with Debezium Server (No Kafka) — Django + Postgres + MongoDB Example</title>
      <dc:creator>Maqbool Thoufeeq T</dc:creator>
      <pubDate>Tue, 29 Apr 2025 16:57:56 +0000</pubDate>
      <link>https://dev.to/maqboolthoufeeq/change-data-capture-cdc-with-debezium-server-no-kafka-django-postgres-mongodb-example-m0h</link>
      <guid>https://dev.to/maqboolthoufeeq/change-data-capture-cdc-with-debezium-server-no-kafka-django-postgres-mongodb-example-m0h</guid>
      <description>&lt;p&gt;When I explored CDC (Change Data Capture) implementations without Kafka, I found very little helpful material online. Most examples heavily depended on Kafka, but for many smaller systems, Kafka can feel too heavy.&lt;/p&gt;

&lt;p&gt;So, I decided to create a clear, working project using Debezium Server (without Kafka) — integrated with Django, PostgreSQL, MongoDB and Mongo Express for Viewing the Changes — and document it for others.&lt;/p&gt;

&lt;p&gt;This article will walk you through the architecture and steps with diagrams and screenshots.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/maqboolthoufeeq/cdc_debezium" rel="noopener noreferrer"&gt;https://github.com/maqboolthoufeeq/cdc_debezium&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F5rxd7d97o0rj8yut9fbk.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.amazonaws.com%2Fuploads%2Farticles%2F5rxd7d97o0rj8yut9fbk.png" alt="Change Data Capture (CDC) with Debezium Server (No Kafka) — Django + Postgres + MongoDB Example" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Overview
&lt;/h2&gt;

&lt;p&gt;This project shows how to capture database changes from a Django application (running on PostgreSQL), stream them using Debezium Server, and store the change events in MongoDB for analysis or auditing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Main Components:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django (Admin Panel &amp;amp; API)&lt;/li&gt;
&lt;li&gt;PostgreSQL (Data Storage)&lt;/li&gt;
&lt;li&gt;Debezium Server (CDC without Kafka)&lt;/li&gt;
&lt;li&gt;MongoDB (Stores Change Events)&lt;/li&gt;
&lt;li&gt;Mongo Express (Web Viewer for MongoDB)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠 Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;Here’s the overall data flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Django Admin updates data&lt;/li&gt;
&lt;li&gt;PostgreSQL stores the updated data&lt;/li&gt;
&lt;li&gt;Debezium Server detects changes&lt;/li&gt;
&lt;li&gt;Debezium Server sends CDC events to MongoDB&lt;/li&gt;
&lt;li&gt;Mongo Express lets us easily view the events&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🚀 How to Run the Project
&lt;/h2&gt;

&lt;p&gt;Folder Structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdc_debeizum/
├── README.md
└── cdc_debezium_server_mongo_django/
    ├── docker-compose.yml
    ├── debezium-config
    ├── postgres-conf
    └── django
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/maqboolthoufeeq/cdc_debezium.git
cd cdc_debezium/cdc_debezium_server_mongo_django
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Build and Start the Services:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose build
docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔥 First Look After Startup
&lt;/h2&gt;

&lt;p&gt;Once everything is running, navigate to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service Navigation Panel: &lt;code&gt;http://localhost:8000/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Django Admin Panel: &lt;code&gt;http://localhost:8000/admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Mongo Express Dashboard: &lt;code&gt;http://localhost:8086&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Service Navigation Panel will show the other navigation links (Default passwords are already configured automatically.)&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Step-by-Step Flow
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;code&gt;http://localhost:8000/&lt;/code&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F948axv8li6xpdqcitebs.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.amazonaws.com%2Fuploads%2Farticles%2F948axv8li6xpdqcitebs.png" alt="Image description" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://localhost:8000/admin" rel="noopener noreferrer"&gt;http://localhost:8000/admin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fpt4wj87pmi7j9zcekbfd.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.amazonaws.com%2Fuploads%2Farticles%2Fpt4wj87pmi7j9zcekbfd.png" alt="Image description" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://localhost:8086" rel="noopener noreferrer"&gt;http://localhost:8086&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F19vj1y32gtck2x9cxbii.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.amazonaws.com%2Fuploads%2Farticles%2F19vj1y32gtck2x9cxbii.png" alt="Image description" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are enough for your initial Experience, More technical details will be given below&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Key Technical Configurations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. PostgreSQL Setup (WAL Configuration)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;postgresql.conf&lt;/code&gt;, &lt;code&gt;(cdc_debezium_server_mongo_django/postgres-conf/postgresql.conf )&lt;/code&gt; we ensure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wal_level = logical
max_wal_senders = 1000
max_replication_slots = 1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Debezium Server Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;application.properties&lt;/code&gt;&lt;code&gt;(cdc_debezium_server_mongo_django/debezium-config/application.properties)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ============================================================================
# DEBEZIUM POSTGRESQL CDC CONFIGURATION
# ============================================================================

# Core Connector Configuration
# ----------------------------
debezium.source.connector.class=io.debezium.connector.postgresql.PostgresConnector
debezium.source.offset.storage.file.filename=data/offsets.dat
debezium.source.offset.flush.interval.ms=60000
debezium.source.provide.transaction.metadata=false

# PostgreSQL Connection Details
# ----------------------------
debezium.source.database.hostname=postgres
debezium.source.database.port=5432
debezium.source.database.user=user
debezium.source.database.password=password
debezium.source.database.dbname=mydb
debezium.source.database.server.name=postgres_server

# Change Data Capture (CDC) Configuration
# ---------------------------------------
# Using pgoutput logical decoding plugin (native PostgreSQL)
debezium.source.plugin.name=pgoutput
debezium.source.publication.name=dbz_publication
# Only capture changes from specific tables
debezium.source.table.include.list=public.cdc_app_post,public.cdc_app_category
debezium.source.schema.include.list=public
# Don't emit a tombstone event on DELETE operations
debezium.source.tombstones.on.delete=false
# Always take an initial snapshot when starting
debezium.source.snapshot.mode=initial
# Include schema change events
debezium.source.include.schema.changes=true
# Handle decimal types precisely
debezium.source.decimal.handling.mode=precise

# Topic Configuration
# ------------------
# Required prefix for topic names even without Kafka
debezium.source.topic.prefix=postgres_cdc

# Data Format Configuration
# ------------------------
debezium.format.value=json
debezium.format.key.converter=org.apache.kafka.connect.json.JsonConverter
debezium.format.value.converter=org.apache.kafka.connect.json.JsonConverter
# Disable schema information in messages
debezium.source.key.converter.schemas.enable=false
debezium.source.value.converter.schemas.enable=false

# HTTP Sink Configuration
# ----------------------
debezium.sink.type=http
debezium.sink.http.url=http://django:8000/api/cdc/
debezium.sink.http.timeout.ms=30000
debezium.sink.http.retry.interval.ms=30000
debezium.sink.http.header.Content-Type=application/json

# Logging Configuration
# --------------------
quarkus.log.console.json=false

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We specify &lt;code&gt;pgoutput&lt;/code&gt; as the decoding plugin.&lt;/li&gt;
&lt;li&gt;We explicitly limit capture to selected tables (&lt;code&gt;Post&lt;/code&gt;, &lt;code&gt;Category&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;CDC events are posted directly to an HTTP endpoint or written to MongoDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Django Initialization Script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom management command &lt;code&gt;init_cdc.py&lt;/code&gt; (&lt;code&gt;cdc_debezium_server_mongo_django/django/cdc_app/management/commands/init_cdc.py&lt;/code&gt;) sets up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logical replication slots.&lt;/li&gt;
&lt;li&gt;Publications for selected tables.&lt;/li&gt;
&lt;li&gt;Replica identities (so we can capture &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; states).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.conf import settings
from django.core.management.base import BaseCommand
from django.db import connection

from cdc_app.models import Post, Category

DEBEZIUM_PUBLICATION_NAME = getattr(
    settings, "DEBEZIUM_PUBLICATION_NAME", "dbz_publication"
)
DEBEZIUM_SLOT_NAME = getattr(settings, "DEBEZIUM_SLOT_NAME", "debezium")

# Get the actual table names from the models
TABLES_FOR_CDC = [Post._meta.db_table, Category._meta.db_table]


class Command(BaseCommand):
    help = (
        "Initialize CDC by setting replication permissions, creating a "
        + "logical replication slot (if needed), and configuring publications and "
        + "replica identities for the specified models."
    )

    def handle(self, *args, **options):
        self.stdout.write("Starting CDC initialization...")

        # Get current database user from connection
        with connection.cursor() as cursor:
            cursor.execute("SELECT current_user")
            current_user = cursor.fetchone()[0]
            self.stdout.write(f"Current database user: {current_user}")

        # Global commands: these apply to the entire database.
        global_commands = [
            f'ALTER ROLE "{current_user}" WITH REPLICATION',
            (
                f"SELECT pg_create_logical_replication_slot('{DEBEZIUM_SLOT_NAME}', 'pgoutput') "
                f"WHERE NOT EXISTS (SELECT 1 FROM pg_replication_slots WHERE "
                f"slot_name = '{DEBEZIUM_SLOT_NAME}')"
            ),
        ]
        with connection.cursor() as cursor:
            for command in global_commands:
                self.stdout.write(f"Executing global command: {command}")
                try:
                    cursor.execute(command)
                except Exception as e:
                    self.stderr.write(
                        f"Error executing global command:\n{command}\nError: {e}"
                    )
                    raise e

        with connection.cursor() as cursor:
            # Determine which of the specified tables exist in the database.
            existing_tables = []
            for table in TABLES_FOR_CDC:
                cursor.execute(
                    """
                    SELECT EXISTS (
                        SELECT 1
                        FROM information_schema.tables
                        WHERE table_schema = current_schema()
                            AND table_name = %s
                    )
                    """,
                    [table],
                )
                exists = cursor.fetchone()[0]
                if exists:
                    existing_tables.append(table)
                else:
                    self.stdout.write(f"Table '{table}' does not exist, skipping.")

            # Skip CDC conf if none of the tables exist.
            if not existing_tables:
                self.stdout.write(
                    "No specified tables found, skipping CDC configuration."
                )
                return

            # Create a publication with the existing tables.
            publication_name = DEBEZIUM_PUBLICATION_NAME
            tables_sql = ", ".join(f'"{table}"' for table in existing_tables)
            publication_command = f"""
                DO $$
                BEGIN
                    IF NOT EXISTS (
                        SELECT 1
                        FROM pg_publication
                        WHERE pubname = '{publication_name}'
                    ) THEN
                        CREATE PUBLICATION {publication_name}
                        FOR TABLE {tables_sql};
                    END IF;
                END$$;
            """

            self.stdout.write(
                f"Executing publication command:\n{publication_command.strip()}"
            )
            try:
                cursor.execute(publication_command)
            except Exception as e:
                self.stderr.write(f"Error executing publication command: {e}")
                raise e

            # Alter each table to use full replica identity.
            for table in existing_tables:
                alter_command = f'ALTER TABLE "{table}" REPLICA IDENTITY FULL'
                self.stdout.write(f"Executing: {alter_command}")
                try:
                    cursor.execute(alter_command)
                except Exception as e:
                    self.stderr.write(
                        f"Error executing alter command for table '{table}': {e}"
                    )
                    raise e

        self.stdout.write(self.style.SUCCESS("CDC initialization complete."))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script auto-runs during Django container startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Docker Compose&lt;/strong&gt;&lt;br&gt;
Key services in &lt;code&gt;docker-compose.yaml&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;postgres (Debezium-enabled by the commad)&lt;/li&gt;
&lt;li&gt;django&lt;/li&gt;
&lt;li&gt;debezium (Debezium Server 3.0)&lt;/li&gt;
&lt;li&gt;mongodb&lt;/li&gt;
&lt;li&gt;mongo-express&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All services are on a shared Docker network for easy communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Change Data Capture doesn’t have to be complicated. With Debezium Server and smart choices like MongoDB as a sink, you can build powerful, event-driven architectures — without the heavy lifting of Kafka.&lt;/p&gt;

&lt;p&gt;Feel free to clone, modify, and extend the project. I built this because I couldn’t find a good resource online — so now you have one!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/maqboolthoufeeq/cdc_debezium" rel="noopener noreferrer"&gt;https://github.com/maqboolthoufeeq/cdc_debezium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it helpful, consider ⭐ starring the repo!&lt;/p&gt;

&lt;h1&gt;
  
  
  ChangeDataCapture #Debezium #DebeziumServer #NoKafka #CDC #Django #PostgreSQL #MongoDB #DockerCompose #Microservices #EventDrivenArchitecture #SoftwareEngineering #BackendDevelopment #DatabaseEngineering #OpenSource #FullStackDevelopment #SystemDesign #PythonDeveloper #DataEngineering #DatabaseReplication #DevOps #CloudNative
&lt;/h1&gt;

</description>
      <category>changedatacapture</category>
      <category>systemdesign</category>
      <category>debezium</category>
      <category>cdc</category>
    </item>
  </channel>
</rss>
