<?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: Xitong Shan</title>
    <description>The latest articles on DEV Community by Xitong Shan (@sxt12356).</description>
    <link>https://dev.to/sxt12356</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%2F4089872%2F861a99a5-d32e-4ad5-89c1-fcc2b19fd1ce.png</url>
      <title>DEV Community: Xitong Shan</title>
      <link>https://dev.to/sxt12356</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sxt12356"/>
    <language>en</language>
    <item>
      <title>Fixing a pgvector CI mismatch in a FastAPI RAG backend</title>
      <dc:creator>Xitong Shan</dc:creator>
      <pubDate>Sat, 22 Aug 2026 15:33:05 +0000</pubDate>
      <link>https://dev.to/sxt12356/fixing-a-pgvector-ci-mismatch-in-a-fastapi-rag-backend-3gm2</link>
      <guid>https://dev.to/sxt12356/fixing-a-pgvector-ci-mismatch-in-a-fastapi-rag-backend-3gm2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Clear the Lineup&lt;/a&gt;, powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/sxt12356/mini-agent" rel="noopener noreferrer"&gt;&lt;code&gt;mini-agent&lt;/code&gt;&lt;/a&gt; is a public FastAPI backend for an AI support-agent demo. Its test suite covers API behavior, authentication, rate limiting, approval flows, and PostgreSQL/pgvector-backed retrieval.&lt;/p&gt;

&lt;p&gt;The GitHub Actions workflow starts PostgreSQL and Redis service containers before running the Python test suite. The application database initialization also executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dependency is also visible in the &lt;a href="https://github.com/sxt12356/mini-agent/blob/4f0fc4f8ecdc75288fd43eaddbeef9bc51045640/mini_agent/db/models.py#L54-L63" rel="noopener noreferrer"&gt;&lt;code&gt;DocumentChunk.embedding&lt;/code&gt;&lt;/a&gt; column, which uses pgvector's &lt;code&gt;Vector&lt;/code&gt; type. That made the database image part of the test contract, not just incidental infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug Fix or Performance Improvement
&lt;/h2&gt;

&lt;p&gt;On August 12, 2026, the CI run for the preceding commit reached the test step and failed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sxt12356/mini-agent/actions/runs/31558609459" rel="noopener noreferrer"&gt;Failed workflow run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sxt12356/mini-agent/commit/e6378f7e79543a0f363d1171cca8daae7e946d55" rel="noopener noreferrer"&gt;Commit tested by that run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow was using the general-purpose &lt;code&gt;postgres:17-alpine&lt;/code&gt; service image, while the application required the pgvector extension during database initialization. The test environment therefore did not match the database capability required by the code.&lt;/p&gt;

&lt;p&gt;The failure was specific enough to avoid a broad rewrite: the container initialized successfully, dependency installation passed, and the workflow stopped only at &lt;strong&gt;Run tests&lt;/strong&gt;. That pointed to the application/database boundary rather than the GitHub Actions runner or Python installation.&lt;/p&gt;

&lt;p&gt;The fix changed one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; services:
   postgres:
&lt;span class="gd"&gt;-    image: postgres:17-alpine
&lt;/span&gt;&lt;span class="gi"&gt;+    image: pgvector/pgvector:0.8.6-pg17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full change: &lt;a href="https://github.com/sxt12356/mini-agent/commit/4f0fc4f8ecdc75288fd43eaddbeef9bc51045640" rel="noopener noreferrer"&gt;Use pgvector image in CI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The PostgreSQL major version, credentials, port mapping, health check, application environment, dependency installation, and test command all remained unchanged. This kept the patch narrow and made the CI database expose the same required extension as the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The evidence is a direct before-and-after pair:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The preceding workflow failed at &lt;strong&gt;Run tests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The one-line database-image commit triggered a new workflow.&lt;/li&gt;
&lt;li&gt;The new run completed &lt;strong&gt;Run tests&lt;/strong&gt; successfully and the overall workflow passed.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sxt12356/mini-agent/actions/runs/31558609459" rel="noopener noreferrer"&gt;Failed run: 31558609459&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sxt12356/mini-agent/actions/runs/31559054400" rel="noopener noreferrer"&gt;Passing run: 31559054400&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL service image&lt;/td&gt;
&lt;td&gt;&lt;code&gt;postgres:17-alpine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pgvector/pgvector:0.8.6-pg17&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container initialization&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency installation&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Run tests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Failed&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overall workflow&lt;/td&gt;
&lt;td&gt;Failed&lt;/td&gt;
&lt;td&gt;Passed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No tests were disabled, no failure was ignored, and no application feature was added to make the build green.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Improvements
&lt;/h2&gt;

&lt;p&gt;The visible patch is small, but it fixes an important reliability boundary: integration tests are only meaningful when their service dependencies provide the capabilities the application actually uses.&lt;/p&gt;

&lt;p&gt;The change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;restores the full CI test run;&lt;/li&gt;
&lt;li&gt;makes the PostgreSQL service compatible with the repository's pgvector-backed model;&lt;/li&gt;
&lt;li&gt;preserves PostgreSQL 17 rather than changing database versions as a side effect;&lt;/li&gt;
&lt;li&gt;avoids installing database extensions ad hoc during every CI run;&lt;/li&gt;
&lt;li&gt;keeps the workflow readable and reproducible with a pinned pgvector image tag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The general lesson is to treat database extensions as explicit runtime dependencies. If application startup creates or queries extension-backed types, CI must supply that extension too. A healthy generic PostgreSQL container is not enough when the application's schema contract includes extension-defined types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosure
&lt;/h2&gt;

&lt;p&gt;The code change, commit timestamps, and workflow outcomes are public and independently inspectable through the links above. This write-up was prepared with AI-assisted editing and was personally reviewed by the entrant before publication. No production data, customer credentials, or private incident details are included.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>postgres</category>
      <category>python</category>
    </item>
  </channel>
</rss>
