<?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>Forem: Çalgan Aygün</title>
    <description>The latest articles on Forem by Çalgan Aygün (@calganaygun).</description>
    <link>https://forem.com/calganaygun</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%2F389991%2F259e54a7-492e-4848-b98e-950b56893521.jpg</url>
      <title>Forem: Çalgan Aygün</title>
      <link>https://forem.com/calganaygun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/calganaygun"/>
    <language>en</language>
    <item>
      <title>Resisting the Eye of the Machine: A Reflection on AI and Data Ownership</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Tue, 24 Feb 2026 21:08:49 +0000</pubDate>
      <link>https://forem.com/calganaygun/resisting-the-eye-of-the-machine-a-reflection-on-ai-and-data-ownership-510m</link>
      <guid>https://forem.com/calganaygun/resisting-the-eye-of-the-machine-a-reflection-on-ai-and-data-ownership-510m</guid>
      <description>&lt;p&gt;AI both creates and consumes. For someone like me, who’s invested deeply in both the benefits and risks of these evolving systems, the duality is impossible to ignore. On one hand, AI supplements creativity, fast-tracks productivity, and offers insights unprecedented in human history. On the other, AI is a voracious consumer that treats every public thought, image, and pixel as a potential resource for improvement—its improvement, not ours.&lt;/p&gt;

&lt;p&gt;What happens to ideas when they’re not just shared, but consumed, repurposed, and disjointed from their original intention? This is not a fight against inevitable progress but an invitation to consider where the boundaries should lie.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hunger of the Machine
&lt;/h2&gt;

&lt;p&gt;Today’s AI systems are participants in a digital ecosystem. To feed their model-building appetite, they consume everything: tweets, screenshots, vague status updates, unfinished sketches, throwaway jokes—anything to refine prediction and replication capabilities. These systems don’t ask for permission; most of the time, they don’t even acknowledge the humans who originally created the content.&lt;/p&gt;

&lt;p&gt;As someone interested in sparking friction within this process, I’ve explored ways to actively undermine AI’s consumption. One approach stems from visual obfuscation principles to disrupt AI readers at the OCR level, reducing their ability to reconstruct coherent text segments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Segmentation and My Implementation
&lt;/h3&gt;

&lt;p&gt;The core idea relies on &lt;strong&gt;radical dynamic segmentation&lt;/strong&gt;. Imagine text that never fully "settles"—it pulses, shifts, even disassembles itself momentarily. While the human eye has an incredible ability to "fill in the blanks" and interpret movement, machines struggle with this flux.&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%2Fbgyd4yhqsq3cpemuzgis.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%2Fbgyd4yhqsq3cpemuzgis.png" alt="Initial concept from h43z." width="598" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/h43z/status/1949241540465045853" rel="noopener noreferrer"&gt;h43z's initial concept&lt;/a&gt; focused on kinetic text—characters in constant motion to disrupt machine vision. This was the spark that got me thinking, but I took a different route: breaking characters into partial segments that flash independently. The chunking method was something I figured out through experimentation.&lt;/p&gt;

&lt;p&gt;The implementation is JavaScript-based, using Canvas to analyze each character's pixels and fragment them in various ways—radial slices, concentric rings, diagonal strips, random distributions. Each chunk flashes at randomized intervals. The result: text that humans can read but machines can't easily parse.&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%2Fd3zm3sgzv4hz9n3zg0yd.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%2Fd3zm3sgzv4hz9n3zg0yd.png" alt="One of my tested concepts, A screenshot shows 'Hello dev.to'" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tested against OCR libraries like Tesseract and even LLM-adjacent pipelines. The simpler systems failed completely. Modern Live/Video APIs struggled but occasionally recovered—revealing both the method's potential and its limits.&lt;/p&gt;

&lt;p&gt;Why it works: It exploits the gap between human and machine perception. We thrive on approximation and motion. Machines expect clean, static data. Every fragmented flash introduces chaos that challenges their assumptions about how information should look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations and Lessons
&lt;/h3&gt;

&lt;p&gt;Technology can’t be a self-contained solution to problems of technological overreach. One critical limitation is that dynamic segmentation, while effective on smaller scales, is computationally expensive to produce and impractical for systems requiring long text readability.&lt;/p&gt;

&lt;p&gt;Moreover, it raises a practical question: How many people would opt to obfuscate their content actively? To scale such efforts and normalize resistance, the tools need to be seamless, almost invisible to the writer. A browser extension that dynamically applies segmentation while retaining human readability—a future goal—might bridge this gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Philosophical Trade-Offs
&lt;/h2&gt;

&lt;p&gt;This technical exploration also emphasizes deeper philosophical questions. By participating in this cat-and-mouse game against AI, do we solve the problem or play into its competitive escalation? As much as the act of resistance feels gratifying, it’s worth asking: What happens when the effort to defend against machines becomes indistinguishable from innovations driving them forward?&lt;/p&gt;

&lt;p&gt;AI reveals how much has been surrendered—privacy, ownership, sometimes even the joy of creating for humans rather than systems. But agency remains deeply human. Perhaps that’s the key takeaway: less about domination and more about choosing what remains ours.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing: Toward Balancing Agency
&lt;/h2&gt;

&lt;p&gt;Dynamic segmentation obviously is not a silver bullet. It won’t end AI overconsumption, but it does add another tool to the resistance. My experiments aim to create what friction I can—disrupting the expectation that AI must own everything it sees. At the heart of this is the hope that small, deliberate acts can start larger conversations about human ownership in an AI-driven culture.&lt;/p&gt;

&lt;p&gt;As experiments continue, the tension between control and participation stays alive. To stabilize both technology and thought, we’ll need boundaries that don’t eliminate creativity but celebrate and protect its imperfection.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Acknowledgments:&lt;/strong&gt; To h43z, whose kinetic text concept was the initial inspiration that sparked my thinking on this problem. While their approach focused on character movement, it pushed me to explore the chunking and partial segmentation methods documented here.&lt;/p&gt;




&lt;p&gt;Additional References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My implementation of dynamic segmentation tests: &lt;a href="http://e.43z.one/ega5yzz" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The foundational thought by h43z: &lt;a href="https://x.com/h43z/status/1949241540465045853" rel="noopener noreferrer"&gt;Original Tweet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>data</category>
      <category>discuss</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Redefining Event-Driven Architecture on Google Cloud</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Mon, 16 Feb 2026 19:10:10 +0000</pubDate>
      <link>https://forem.com/gde/redefining-event-driven-architecture-on-google-cloud-5abj</link>
      <guid>https://forem.com/gde/redefining-event-driven-architecture-on-google-cloud-5abj</guid>
      <description>&lt;p&gt;Building event-driven systems with Cloud Run, Pub/Sub, and Eventarc is a powerful pattern, but the gap between "Hello World" tutorials and production stability is wide. These are the hard-won lessons from the trenches of Google Cloud serverless architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Choosing Your Transport: Eventarc vs. Pub/Sub
&lt;/h2&gt;

&lt;p&gt;While Eventarc often uses Pub/Sub under the hood, the choice of which to interface with directly depends on your source and required control.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Eventarc&lt;/th&gt;
&lt;th&gt;Direct Pub/Sub&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GCP-native events (GCS, Firestore, Audit Logs)&lt;/td&gt;
&lt;td&gt;Custom inter-service messaging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed wrapper, high convenience&lt;/td&gt;
&lt;td&gt;Manual configuration, high control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Filtering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in attribute filtering&lt;/td&gt;
&lt;td&gt;Fine-grained policies &amp;amp; custom attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IAM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;eventarc.eventReceiver&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;pubsub.subscriber&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Use Eventarc for "plumbing" Google Cloud events. Use Direct Pub/Sub when you need a custom event bus or specific retry/ordering logic.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. The Infrastructure Reality Check
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Idempotency Requirement
&lt;/h3&gt;

&lt;p&gt;Pub/Sub guarantees &lt;strong&gt;at-least-once&lt;/strong&gt; delivery by default. While exactly-once delivery exists as an opt-in feature, your consumers must assume duplicates will happen. If your handler isn't idempotent, you risk double-charging users or corrupting state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Non-Negotiable Flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract a unique &lt;strong&gt;Idempotency Key&lt;/strong&gt; (UUID/Hash) from the event.&lt;/li&gt;
&lt;li&gt;Check a fast-access cache (Memorystore or Firestore) for the key.&lt;/li&gt;
&lt;li&gt;If present, &lt;strong&gt;discard&lt;/strong&gt; the message as a duplicate.&lt;/li&gt;
&lt;li&gt;If absent, process the event and &lt;strong&gt;store&lt;/strong&gt; the key with a TTL.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Managing Cold Starts
&lt;/h3&gt;

&lt;p&gt;Cloud Run’s "scale to zero" is a budget-saver but a latency-killer. A container startup typically adds &lt;strong&gt;2–8 seconds&lt;/strong&gt; to the first request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; Set &lt;code&gt;min-instances&lt;/code&gt; for latency-critical paths (this incurs cost).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Alternative:&lt;/strong&gt; Use &lt;strong&gt;Cloud Run Jobs&lt;/strong&gt; for asynchronous batch processing where start-time overhead is less relevant.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Eventarc Propagation Delays
&lt;/h3&gt;

&lt;p&gt;When deploying Eventarc triggers via Terraform or CLI, filtering rules can take &lt;strong&gt;60–120 seconds&lt;/strong&gt; to propagate across the Google network.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Production Fix:&lt;/strong&gt; Build a "warm-up" delay into your CI/CD pipeline. Do not trigger integration tests immediately after a successful deployment, or you will see intermittent, false-positive failures.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Calculating Realistic Costs
&lt;/h2&gt;

&lt;p&gt;Tutorials often suggest serverless is "pennies," but at scale, the math changes. Pub/Sub is billed at &lt;strong&gt;$40 per TiB&lt;/strong&gt;, with a &lt;strong&gt;1 KB minimum&lt;/strong&gt; per message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: 10M Events/Day (300M/Month)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Volume:&lt;/strong&gt; 300M messages × 1 KB (min size) ≈ &lt;strong&gt;293 GiB (0.286 TiB)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingest &amp;amp; Delivery:&lt;/strong&gt; (0.286 TiB × $40) + (0.286 TiB × $40) = &lt;strong&gt;$23/month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute (Cloud Run):&lt;/strong&gt; 300M invocations (assuming 1s duration, 512MB RAM) ≈ &lt;strong&gt;$150–$200/month&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; ~$175–$225/month. Significant, but highly predictable if you monitor message size and invocation duration.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Advanced Production Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Regional Co-location
&lt;/h3&gt;

&lt;p&gt;Eventarc triggers for multi-region services (like Firestore &lt;code&gt;nam5&lt;/code&gt;) are often pinned to specific regions (e.g., &lt;code&gt;us-central1&lt;/code&gt;). If your Cloud Run service resides elsewhere, you will incur &lt;strong&gt;cross-region egress charges&lt;/strong&gt; and increased latency. Always verify the region mapping table in the GCP documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payload Sanitization at the Edge
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;Eventarc Advanced&lt;/strong&gt;, you can use Common Expression Language (CEL) to transform or redact payloads before they reach the consumer. This is vital for PII compliance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Example: Redacting an email address in-flight
message.setField("data.email", re.extract(message.data.email, "(^.).*@(.*)", "\\1***@\\2"))

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observability and Dead-Letter Topics (DLTs)
&lt;/h3&gt;

&lt;p&gt;In a distributed system, an event can "disappear" if a filter drops it or a consumer fails silently.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DLTs:&lt;/strong&gt; Every subscription must have a Dead-Letter Topic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting:&lt;/strong&gt; Monitor the &lt;code&gt;subscription/dead_letter_message_count&lt;/code&gt; metric. A rising count is your first sign of a logic bug or schema mismatch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracing:&lt;/strong&gt; Use OpenTelemetry to inject &lt;strong&gt;Trace IDs&lt;/strong&gt; into event attributes, allowing you to follow a single request from the producer through the bus to the consumer logs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. When to Avoid Event-Driven
&lt;/h2&gt;

&lt;p&gt;Don't "cargo-cult" this architecture if it doesn't fit your needs. Skip it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You require &lt;strong&gt;strong consistency&lt;/strong&gt; and immediate transactions.&lt;/li&gt;
&lt;li&gt;Your end-to-end latency requirements are &lt;strong&gt;&amp;lt; 100ms&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The overhead of debugging distributed traces outweighs the scaling benefits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, stick to &lt;strong&gt;Synchronous gRPC/HTTP&lt;/strong&gt; or &lt;strong&gt;Cloud Workflows&lt;/strong&gt; for structured orchestration.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Takeaway
&lt;/h3&gt;

&lt;p&gt;The combination of Cloud Run and Eventarc is one of the most robust patterns in 2026. By respecting the boundaries of the platform—accounting for propagation delays, ensuring idempotency, and co-locating regions—you can build a system that scales effortlessly from zero to millions of events.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>googlecloud</category>
      <category>serverless</category>
    </item>
    <item>
      <title>A CAPTCHA Bypass Technique: Audio Files</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Fri, 30 Jan 2026 12:38:29 +0000</pubDate>
      <link>https://forem.com/calganaygun/a-captcha-bypass-technique-audio-files-315k</link>
      <guid>https://forem.com/calganaygun/a-captcha-bypass-technique-audio-files-315k</guid>
      <description>&lt;p&gt;This is a draft write-up from 2019, documenting a CAPTCHA bypass technique I discovered back then. All code and images shown are examples for educational purposes.&lt;/p&gt;




&lt;p&gt;One day back in 2019, I got tired of repeatedly logging into my school's student system just to enroll in a full class. Then a lightbulb went off in my head: I could automate these attempts and refocus on my actual work.&lt;/p&gt;

&lt;p&gt;When it comes to automating website processes, I love using &lt;a href="https://en.wikipedia.org/wiki/Userscript" rel="noopener noreferrer"&gt;user scripts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Automation Plan
&lt;/h2&gt;

&lt;p&gt;Our school system expired user sessions after a while, even if you were actively working. So first, I needed to automate the login process. Once successfully logged in, navigating and enrolling in a class would be straightforward (just some click event magic).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Login UI
&lt;/h2&gt;

&lt;p&gt;The school system had an internally managed CAPTCHA service. It displayed two numbers and asked for their sum. The images were slightly corrupted—but not enough to prevent OCR. However, I didn't want to rely on any API or image processing system to solve this CAPTCHA.&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%2F63iiiylbkwj5rfrmgr4y.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%2F63iiiylbkwj5rfrmgr4y.png" alt="Example captcha image" width="442" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Inspecting the Audio Service for CAPTCHA
&lt;/h2&gt;

&lt;p&gt;After deciding not to use any image-related service, I started inspecting the network traffic of the login system. I noticed that the answer to the generated CAPTCHA was stored server-side in a session associated with me.&lt;/p&gt;

&lt;p&gt;When I clicked the audio playback button, I realized it was reading out the answer directly. Two different endpoints returned two different audio files, split into tens and ones digits.&lt;/p&gt;

&lt;p&gt;The audio system seemed like a perfect route for me. I had no intention of feeding these audio files into a speech-to-text service—I was looking for the fastest, hackiest solution possible.&lt;/p&gt;

&lt;p&gt;Since the same audio files should have the same file size, I decided to test this hypothesis first.&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%2Fvg4vgyuvgzaz0a1d7vd4.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%2Fvg4vgyuvgzaz0a1d7vd4.png" alt="Example HTTP traffic" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And bingo! By mapping each tens and ones digit to their file sizes beforehand, I could automatically determine the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Solution
&lt;/h2&gt;

&lt;p&gt;Here's an example of how the code worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example mapping of file sizes to digit values&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 0 tens&lt;/span&gt;
  &lt;span class="mi"&gt;1456&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// 1 ten&lt;/span&gt;
  &lt;span class="mi"&gt;1567&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// 2 tens&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;987&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// 0 ones&lt;/span&gt;
  &lt;span class="mi"&gt;1023&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 1 one&lt;/span&gt;
  &lt;span class="mi"&gt;1145&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 2 ones&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Example: Fetch audio files and determine answer by file size&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;solveCaptcha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/captcha/audio/tens&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/captcha/audio/ones&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tensResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onesResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tensMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tensSize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;onesMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;onesSize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tensValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;onesValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use it in the login flow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;solveCaptcha&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#captcha-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#login-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I tested this approach, it worked perfectly!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Lessons Learned
&lt;/h2&gt;

&lt;p&gt;This experience taught me a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Look for alternative attack vectors:&lt;/strong&gt; When the obvious solution (OCR) seems complex, there might be simpler paths (audio files, metadata, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security through obscurity fails:&lt;/strong&gt; Just because a CAPTCHA uses audio doesn't mean it's secure—especially if the files are deterministic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File size is metadata:&lt;/strong&gt; Even without processing the content, file properties can leak information&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This technique worked because the audio files were pre-generated and static. A more secure implementation would generate unique audio files or add random noise to prevent size-based fingerprinting.&lt;/p&gt;

</description>
      <category>security</category>
      <category>captcha</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Uncomfortable Truth About AI-Assisted Development</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Wed, 28 Jan 2026 11:59:53 +0000</pubDate>
      <link>https://forem.com/calganaygun/the-uncomfortable-truth-about-ai-assisted-development-4ckp</link>
      <guid>https://forem.com/calganaygun/the-uncomfortable-truth-about-ai-assisted-development-4ckp</guid>
      <description>&lt;p&gt;&lt;em&gt;Or: How We Learned to Stop Worrying and Start Debugging at 2am&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I need to tell you about a report that made me uncomfortable. Not because it revealed anything shocking, but because it quantified what I've been watching happen in real-time across engineering teams for the past year.&lt;/p&gt;

&lt;p&gt;CodeRabbit analyzed 470 pull requests — 320 co-authored by AI, 150 written by humans. The headline number: &lt;strong&gt;AI-generated code contains 1.7x more issues than human-written code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But that's not the uncomfortable part. The uncomfortable part is that we already knew this. We just chose not to measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Velocity Trap
&lt;/h2&gt;

&lt;p&gt;Here's what's happening on the ground:&lt;/p&gt;

&lt;p&gt;Teams adopted AI coding assistants in 2024. By 2025, they're shipping 20% more PRs per developer. Product managers are thrilled. Engineers feel productive. The metrics look great.&lt;/p&gt;

&lt;p&gt;Then production incidents spike by 23.5%.&lt;/p&gt;

&lt;p&gt;At first, you blame other factors. Infrastructure changes. New team members. Bad luck. But when you dig into the post-mortems, a pattern emerges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A null pointer dereference that should have been caught by basic error handling&lt;/li&gt;
&lt;li&gt;Hardcoded credentials that somehow made it through review&lt;/li&gt;
&lt;li&gt;A database query executing 500 times in a loop instead of being batched&lt;/li&gt;
&lt;li&gt;Exception handling that swallows errors and returns success anyway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't exotic bugs. They're &lt;em&gt;boring&lt;/em&gt; bugs. The kind a junior developer makes in their first month. The kind that code review is supposed to catch.&lt;/p&gt;

&lt;p&gt;Except we're not reviewing like we used to. Because the code &lt;em&gt;looks fine&lt;/em&gt;. It compiles. It follows naming conventions. The structure makes sense. So we skim it, assume the AI got it right, and hit approve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Numbers Actually Mean
&lt;/h2&gt;

&lt;p&gt;Let's break down what CodeRabbit found, because the devil is in the details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic errors: 2x higher&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Algorithm/business logic: 2.25x&lt;/li&gt;
&lt;li&gt;Concurrency control: 2.29x&lt;/li&gt;
&lt;li&gt;Null handling: 2.27x&lt;/li&gt;
&lt;li&gt;Exception handling: 1.97x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells you something fundamental: &lt;strong&gt;AI doesn't understand execution flow&lt;/strong&gt;. It pattern matches syntax. It knows what error handling &lt;em&gt;looks like&lt;/em&gt;, but not when you actually need it. It generates code that passes the happy path and explodes on edge cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security vulnerabilities: 1.57x higher&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XSS injection: 2.74x&lt;/li&gt;
&lt;li&gt;Insecure object references: 1.91x&lt;/li&gt;
&lt;li&gt;Password handling: 1.88x&lt;/li&gt;
&lt;li&gt;Insecure deserialization: 1.82x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the scary one. Because security bugs don't just crash your app—they compromise your users. And AI is literally trained on public code repositories, including all the insecure code that's been written over the past two decades. It's regurgitating attack vectors from 2015 Stack Overflow answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance issues: 7.9x more I/O problems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one made me laugh, then cry. AI optimizes for "code that works" not "code that works &lt;em&gt;efficiently&lt;/em&gt;". Why batch database queries when you can just loop? Why cache when you can fetch? It's technically correct. It's also a production disaster waiting to happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code quality: 3.15x worse readability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The irony here is brutal. One of the selling points of AI assistants is that they write "clean code". Except what they actually write is verbose, repetitive code with inconsistent naming and unnecessary abstraction. It's &lt;em&gt;formatted&lt;/em&gt; nicely. That's not the same thing as &lt;em&gt;readable&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 90th Percentile Problem
&lt;/h2&gt;

&lt;p&gt;Here's the number that keeps me up at night: at the 90th percentile, AI PRs contain &lt;strong&gt;26 issues&lt;/strong&gt; versus 12 for humans.&lt;/p&gt;

&lt;p&gt;This means AI doesn't just create more bugs on average — it occasionally creates absolute disasters. Code that's so broken it shouldn't have made it past the IDE, let alone into production.&lt;/p&gt;

&lt;p&gt;And because we're shipping faster, we're hitting these edge cases more often. It's not a theoretical risk. It's a ticking time bomb in your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Hard to Fix
&lt;/h2&gt;

&lt;p&gt;The obvious answer is "just review AI code more carefully". But that misses the psychological trap we've fallen into.&lt;/p&gt;

&lt;p&gt;AI-generated code &lt;em&gt;feels&lt;/em&gt; trustworthy because it's consistently formatted, confidently written, and superficially correct. It doesn't have the telltale signs of junior code like hesitant variable names, inconsistent style, obvious copy-paste errors.&lt;/p&gt;

&lt;p&gt;So your brain does a pattern match: "this looks like senior-level code" → "probably fine" → approve.&lt;/p&gt;

&lt;p&gt;Except it's not senior-level code. It's &lt;em&gt;senior-looking&lt;/em&gt; code generated by a system that has no mental model of what it's building.&lt;/p&gt;

&lt;p&gt;The traditional markers we use for code quality — structure, naming, formatting — have been decoupled from actual correctness. We need new heuristics, and we haven't built them yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Works
&lt;/h2&gt;

&lt;p&gt;I'm not going to tell you to stop using AI assistants. I use them daily. They're legitimately useful for scaffolding, refactoring, and handling boilerplate.&lt;/p&gt;

&lt;p&gt;But here's what I've learned:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Ground the model in your context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't just paste code into ChatGPT and expect it to understand your domain. Give it your architecture docs. Your API contracts. Your error handling conventions. The more context you provide, the less it has to guess.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Treat AI output as untrusted by default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Would you merge code from a contractor you've never worked with before without thorough review? No? Then don't do it for AI.&lt;/p&gt;

&lt;p&gt;Any code touching auth, payments, PII, or critical business logic gets manual review. No exceptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Automate what AI gets wrong&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI is terrible at formatting, naming consistency, and basic security checks. So automate those with linters, formatters, and SAST tools in your CI pipeline.&lt;/p&gt;

&lt;p&gt;Don't waste human review time catching things machines can catch. Use humans for semantic review; does this actually solve the problem correctly?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use independent review tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is CodeRabbit's obvious pitch, but it's also correct: don't use the same AI that generated code to review it. That's like asking someone to grade their own homework.&lt;/p&gt;

&lt;p&gt;Independent static analysis, security scanners, and code review tools catch different classes of bugs than generative models do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Accept the maintenance tax&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI-assisted development is a trade-off: velocity now, maintenance cost later. If you're not willing to pay down the technical debt, don't take on the loan.&lt;/p&gt;

&lt;p&gt;Budget time for refactoring. Expect to fix edge cases in production. Plan for the eventual rewrite when the generated code becomes unmaintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Question
&lt;/h2&gt;

&lt;p&gt;The uncomfortable truth isn't that AI generates bugs. It's that &lt;strong&gt;we're willing to accept more bugs in exchange for speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's a legitimate trade-off in some contexts. Early-stage startups trying to find product-market fit? Ship fast, fix later. Mature companies with millions of users and regulatory compliance? Maybe slow down.&lt;/p&gt;

&lt;p&gt;But let's be honest about what we're doing. We're not "augmenting developer productivity" in a risk-free way. We're shifting the risk/reward curve.&lt;/p&gt;

&lt;p&gt;More features, faster iteration, shorter cycle times; at the cost of more incidents, more maintenance burden, and more time spent debugging.&lt;/p&gt;

&lt;p&gt;Is that worth it? Depends on your context. But you can't answer that question if you're not measuring the cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Next
&lt;/h2&gt;

&lt;p&gt;AI coding assistants aren't going away. They're getting better. Context windows are expanding. Models are learning from feedback. The tooling is improving.&lt;/p&gt;

&lt;p&gt;But the fundamental problem remains: &lt;strong&gt;LLMs are pattern-matching engines, not reasoning systems&lt;/strong&gt;. They don't understand your invariants. They don't trace execution paths. They don't think about failure modes.&lt;/p&gt;

&lt;p&gt;They surface-fit syntax without semantic understanding.&lt;/p&gt;

&lt;p&gt;Until that changes, AI-generated code will always carry a quality tax. The question is whether we're willing to pay it; and whether we're honest about the price.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI code creates 1.7x more issues than human code across logic, security, performance, and maintainability&lt;/li&gt;
&lt;li&gt;The worst AI PRs (90th percentile) contain 26 issues vs 12 for humans; catastrophic failure modes are real&lt;/li&gt;
&lt;li&gt;Teams are shipping 20% more PRs but seeing 23.5% more production incidents&lt;/li&gt;
&lt;li&gt;AI optimizes for "looks correct" not "is correct"; it passes shallow tests but fails on edge cases&lt;/li&gt;
&lt;li&gt;Effective mitigation requires grounding models in context, automating quality checks, and treating AI output as untrusted&lt;/li&gt;
&lt;li&gt;The velocity gain is real, but so is the maintenance cost; choose consciously&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Full CodeRabbit report: &lt;a href="https://www.coderabbit.ai/whitepapers/state-of-AI-vs-human-code-generation-report" rel="noopener noreferrer"&gt;https://www.coderabbit.ai/whitepapers/state-of-AI-vs-human-code-generation-report&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>devops</category>
      <category>ai</category>
      <category>development</category>
    </item>
    <item>
      <title>AI Productivity Tips 1 - SQL Companion Bot with Gemini 1.5 Pro</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Sun, 25 Aug 2024 10:27:36 +0000</pubDate>
      <link>https://forem.com/calganaygun/ai-productivity-tips-1-sql-companion-bot-with-gemini-15-pro-5g2c</link>
      <guid>https://forem.com/calganaygun/ai-productivity-tips-1-sql-companion-bot-with-gemini-15-pro-5g2c</guid>
      <description>&lt;p&gt;In my current role, I often need to analyze database records and evaluate user performance metrics to identify anomalies. However, manually writing these one-off queries across multiple tables isn't efficient, especially when dealing with complex joins. To streamline this process, I turned to AI.&lt;/p&gt;

&lt;p&gt;Here’s a step-by-step guide on how to boost your productivity using AI for SQL queries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start by navigating to &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt; and create a new chat prompt.&lt;/li&gt;
&lt;/ol&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%2Fm9f28cn6ml538h14fqas.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%2Fm9f28cn6ml538h14fqas.png" alt="Google AI Studio Snapshot" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next, set up a SQL Helper system prompt. Provide your database schema in the system prompt, also specify the RDBMS you’re using so that the AI can generate queries with the correct syntax. I tested this with &lt;a href="https://db-book.com/university-lab-dir/sqljs.html" rel="noopener noreferrer"&gt;The DB Book&lt;/a&gt;'s schema.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s an example system prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Act as a DB Admin/SQL Developer and generate the requested SQL queries based on the following DDL/Schema. Provide explanations and ensure that the queries are safe to run in a production environment. Add "Do not forget to review the SQL query before running." to all SQL responses.

RDBMS/SQL Syntax: &amp;lt;Your RDBMS&amp;gt;

My database DDL: &amp;lt;Your database and table DDLs&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Now, ask your query! For example, I asked: &lt;code&gt;I need to identify the students who are enrolled in a course taught by Teacher 1 and list all their other courses in a comma-separated format in a column.&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And just like that, the AI (thanks to Gemini 1.5 Pro) generated the query I needed.&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%2F7572ng29ty4qrzpk1l4j.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%2F7572ng29ty4qrzpk1l4j.png" alt="Chat Snapshot" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>gemini</category>
      <category>productivity</category>
      <category>googlecloud</category>
    </item>
  </channel>
</rss>
