<?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: Serhat</title>
    <description>The latest articles on DEV Community by Serhat (@netaliz).</description>
    <link>https://dev.to/netaliz</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%2F4163789%2F3dca42d4-7792-4dab-95c0-377be423391d.png</url>
      <title>DEV Community: Serhat</title>
      <link>https://dev.to/netaliz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/netaliz"/>
    <language>en</language>
    <item>
      <title>Building a Profit Analytics SaaS for Turkish Marketplace Sellers: Lessons Learned</title>
      <dc:creator>Serhat</dc:creator>
      <pubDate>Mon, 05 Oct 2026 11:42:40 +0000</pubDate>
      <link>https://dev.to/netaliz/building-a-profit-analytics-saas-for-turkish-marketplace-sellers-lessons-learned-28ef</link>
      <guid>https://dev.to/netaliz/building-a-profit-analytics-saas-for-turkish-marketplace-sellers-lessons-learned-28ef</guid>
      <description>&lt;p&gt;Most marketplace sellers in Turkey think they're profitable. Many of them are wrong.&lt;/p&gt;

&lt;p&gt;I'm Serhat Topcu, founder of &lt;strong&gt;&lt;a href="https://netaliz.com" rel="noopener noreferrer"&gt;Netaliz&lt;/a&gt;&lt;/strong&gt;. This is the honest story of building a profit analytics tool for Trendyol sellers: what worked, what surprised me, and what I'm still figuring out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trendyol integration live, Hepsiburada and N11 on the roadmap&lt;/li&gt;
&lt;li&gt;Every sale broken down into 12 separate deduction items&lt;/li&gt;
&lt;li&gt;A demo store anyone can try without signing up&lt;/li&gt;
&lt;li&gt;An AI module that answers customer questions and learns from the seller&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The problem was hiding in plain sight
&lt;/h2&gt;

&lt;p&gt;Talking to marketplace sellers, I kept hearing the same story: sales were growing, but the money at the end of the month didn't match. They were busy, the orders were coming in, and yet the payout always felt smaller than it should be.&lt;/p&gt;

&lt;p&gt;Trendyol's seller panel shows the commission. But the real cost of a sale includes shipping, service fees, withholding tax, VAT, returns, damaged goods and ad spend. Each has its own formula.&lt;/p&gt;

&lt;p&gt;Sellers were trying to track this in Excel. Most of them gave up halfway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; The best problems are the ones people already try to solve with spreadsheets.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. "Just calculate the profit" is never simple
&lt;/h2&gt;

&lt;p&gt;I thought profit was one formula. It's twelve.&lt;/p&gt;

&lt;p&gt;Commission isn't even a fixed number. It changes with the product's price, across multiple tiers. Raise the price by a small amount and you might drop into a different tier and earn &lt;em&gt;less&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So a simple "multiply by the commission rate" approach was wrong. For price suggestions, we ended up solving it numerically: give a target margin, and the system searches for the price that actually hits it, tiers included.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; If your domain has edge cases, they aren't edge cases. They're the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Marketplace APIs have personalities
&lt;/h2&gt;

&lt;p&gt;Integrating with a marketplace API teaches you humility. Timestamps don't always line up the way you expect. Commission data changes. Returns arrive long after the original order.&lt;/p&gt;

&lt;p&gt;The timestamp issue was a good example. An order could appear on one day in our reports and a different day in the seller's panel, depending on how the time was interpreted. To a seller, that doesn't look like a timezone detail. It looks like the numbers are wrong. We ended up adding in-app guides that explain these marketplace quirks right where they show up.&lt;/p&gt;

&lt;p&gt;Our first sync ran on a schedule every 15 minutes. It worked, but sellers watching a live campaign wanted to see sales &lt;em&gt;now&lt;/em&gt;. So we added webhooks for near real-time updates, with the scheduled sync kept as a safety net.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; Never trust a single data path. Build a backup sync from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Trust is a feature
&lt;/h2&gt;

&lt;p&gt;Sellers were giving us access to their store. That's a big ask.&lt;/p&gt;

&lt;p&gt;One of the first questions sellers asked was simple: "Can this break anything in my store?"&lt;/p&gt;

&lt;p&gt;So we made a deliberate decision: Netaliz is &lt;strong&gt;read-only&lt;/strong&gt;. It never changes products, prices or stock. API keys are encrypted with AES-256 envelope encryption, and data is hosted in Turkey.&lt;/p&gt;

&lt;p&gt;We put this right on the landing page, not hidden in a policy document, because that question deserves a clear answer before anyone signs up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; In B2B, what you &lt;em&gt;won't&lt;/em&gt; do can sell better than what you will.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Let people see it before signing up
&lt;/h2&gt;

&lt;p&gt;People hesitated to connect their real store just to "try" a tool.&lt;/p&gt;

&lt;p&gt;The fix was a demo store with sample data and the real interface, no signup required. Visitors can click around, see a red "loss" order, and understand the value in seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; Remove every step between curiosity and the "aha" moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. AI was the feature sellers didn't ask for, but use daily
&lt;/h2&gt;

&lt;p&gt;Sellers receive a constant stream of customer questions. Answering them well takes time.&lt;/p&gt;

&lt;p&gt;We built Netaliz AI to draft replies using the product's details, the seller's brand voice and their own rules. Every answer the seller approves is stored and used as an example for similar future questions, so it gets better over time.&lt;/p&gt;

&lt;p&gt;Nothing is sent automatically by default. The seller reviews and clicks send.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; Human-in-the-loop isn't a limitation. Every approval is free training data.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What I'm still figuring out
&lt;/h2&gt;

&lt;p&gt;Distribution. Building the product turned out to be the easier part.&lt;/p&gt;

&lt;p&gt;Marketplace sellers are busy people. They don't browse software directories or read tech blogs. They live in seller groups, forums and WhatsApp chats, and they trust recommendations from other sellers far more than any ad.&lt;/p&gt;

&lt;p&gt;Reaching them in a way that feels helpful rather than salesy is the problem I'm working on right now. Expanding to Hepsiburada and N11 is the other big challenge, since every marketplace has its own fee structure and its own API quirks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Launch the demo store much earlier. It answers questions no landing page can.&lt;/li&gt;
&lt;li&gt;Start marketing before the product feels "finished". It never will.&lt;/li&gt;
&lt;li&gt;Talk to sellers before writing a single formula.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see what it looks like, here's the demo store with sample data, no signup needed: &lt;a href="https://netaliz.com/demo" rel="noopener noreferrer"&gt;netaliz.com/demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear from anyone building for a local market or integrating with marketplace APIs. What surprised you the most?&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>saas</category>
      <category>startup</category>
      <category>ai</category>
    </item>
    <item>
      <title>How I Built a Self-Improving AI Reply System for E-commerce Sellers with pgvector</title>
      <dc:creator>Serhat</dc:creator>
      <pubDate>Mon, 05 Oct 2026 11:38:44 +0000</pubDate>
      <link>https://dev.to/netaliz/how-i-built-a-self-improving-ai-reply-system-for-e-commerce-sellers-with-pgvector-5ae4</link>
      <guid>https://dev.to/netaliz/how-i-built-a-self-improving-ai-reply-system-for-e-commerce-sellers-with-pgvector-5ae4</guid>
      <description>&lt;p&gt;Marketplace sellers in Turkey get a constant stream of customer questions: "Is this table waterproof?", "Will it fit a small balcony?", "Why are the reviews so bad?". Every unanswered question is a lost sale, but writing thoughtful replies all day doesn't scale.&lt;/p&gt;

&lt;p&gt;While building &lt;a href="https://netaliz.com" rel="noopener noreferrer"&gt;Netaliz&lt;/a&gt;, a profit analytics tool for Trendyol sellers, I added an AI module that drafts replies to these questions. The interesting part isn't calling an LLM. It's making the system &lt;strong&gt;get better every time the seller approves an answer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with "just prompt it"
&lt;/h2&gt;

&lt;p&gt;My first version was simple: send the product info and the question to an LLM, get an answer back. It worked, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answers sounded generic, not like the seller's brand.&lt;/li&gt;
&lt;li&gt;The model didn't know seller-specific rules ("always say shipping takes 1–3 business days").&lt;/li&gt;
&lt;li&gt;It made the same stylistic mistakes over and over, because nothing was learned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sellers were editing almost every draft. That's not automation, that's extra work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture
&lt;/h2&gt;

&lt;p&gt;The final system has four layers that get assembled into the prompt:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Product context:&lt;/strong&gt; material, dimensions, warranty, pulled from the marketplace API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand voice:&lt;/strong&gt; the seller picks a tone (friendly, corporate, or sales-focused) and defines banned words.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template rules:&lt;/strong&gt; hard instructions like "for shipping questions, say 1–3 business days".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Few-shot examples:&lt;/strong&gt; previously approved answers to &lt;em&gt;similar&lt;/em&gt; questions, retrieved with vector search.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Layer 4 is what makes it self-improving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing approved answers with pgvector
&lt;/h2&gt;

&lt;p&gt;Every time a seller approves a draft (or edits and sends it), we store the question, the final answer and an embedding of the question:&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;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;approved_answers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;BIGSERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;store_id&lt;/span&gt;    &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;question&lt;/span&gt;    &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;answer&lt;/span&gt;      &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;embedding&lt;/span&gt;   &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt;  &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;approved_answers&lt;/span&gt;
  &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;hnsw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;vector_cosine_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keeping this in Postgres instead of a separate vector database was a deliberate choice. The data already lives there, it's scoped per store with a simple &lt;code&gt;WHERE&lt;/code&gt;, and it's one less service to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieving similar examples
&lt;/h2&gt;

&lt;p&gt;When a new question comes in, we embed it and pull the closest approved answers from the same store:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;approved_answers&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;store_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those examples go into the prompt as few-shot demonstrations. If a seller always answers sizing questions in a particular way, the model sees that pattern and follows it, without any fine-tuning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structuring the answer
&lt;/h2&gt;

&lt;p&gt;We also give the model a fixed three-step structure, which made answers noticeably more persuasive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Acknowledge the concern:&lt;/strong&gt; show the customer they were heard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give a concrete argument:&lt;/strong&gt; a specific fact about the product (material, warranty, dimensions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close with trust:&lt;/strong&gt; offer further help.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A simplified version of the prompt assembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReplyContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;`You are a customer support writer for a marketplace seller.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Tone: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brandVoice&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Never use: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bannedWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Rules:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;templateRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`- &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Product facts:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Structure: acknowledge the concern, give one concrete argument, close with trust.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Examples of approved answers:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;examples&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Q: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nA: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`Customer question: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keeping humans in control
&lt;/h2&gt;

&lt;p&gt;By default, nothing is sent automatically. The AI drafts, the seller reviews and clicks send. Auto-send is opt-in, and even then the brand voice, banned words and template rules still apply.&lt;/p&gt;

&lt;p&gt;This turned out to matter for two reasons: sellers trust the system more, and every human approval becomes a new training example. The review step &lt;em&gt;is&lt;/em&gt; the learning loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval beats fine-tuning for per-customer style.&lt;/strong&gt; Each store gets its own "memory" instantly, with no training pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Postgres + pgvector is enough&lt;/strong&gt; at this scale. Don't add infrastructure you don't need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-the-loop is a feature, not a limitation.&lt;/strong&gt; It builds trust and generates your best data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're curious about the product side, Netaliz has a demo store with sample data, no signup needed: &lt;a href="https://netaliz.com/demo" rel="noopener noreferrer"&gt;netaliz.com/demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd love to hear how others are handling per-user style in LLM apps. Are you using retrieval, fine-tuning, or something else?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>postgres</category>
      <category>sass</category>
      <category>commerce</category>
    </item>
  </channel>
</rss>
