<?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: Krasimir Petkov</title>
    <description>The latest articles on DEV Community by Krasimir Petkov (@krasimir_petkov_c14f3b461).</description>
    <link>https://dev.to/krasimir_petkov_c14f3b461</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%2F3726717%2Ff8a42df4-583d-4628-b9af-b668c90b6f41.png</url>
      <title>DEV Community: Krasimir Petkov</title>
      <link>https://dev.to/krasimir_petkov_c14f3b461</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krasimir_petkov_c14f3b461"/>
    <language>en</language>
    <item>
      <title>Why an AI Research Answer Can Have Sources and Still Be Wrong</title>
      <dc:creator>Krasimir Petkov</dc:creator>
      <pubDate>Sat, 24 Oct 2026 17:57:52 +0000</pubDate>
      <link>https://dev.to/krasimir_petkov_c14f3b461/why-an-ai-research-answer-can-have-sources-and-still-be-wrong-1h0k</link>
      <guid>https://dev.to/krasimir_petkov_c14f3b461/why-an-ai-research-answer-can-have-sources-and-still-be-wrong-1h0k</guid>
      <description>&lt;h1&gt;
  
  
  Why an AI Research Answer Can Have Sources and Still Be Wrong
&lt;/h1&gt;

&lt;p&gt;I'm building the research engine behind Prizston, an AI platform I'm developing to help people investigate customer problems and evaluate business opportunities.&lt;/p&gt;

&lt;p&gt;One of the biggest challenges I've encountered isn't getting AI to produce an answer.&lt;/p&gt;

&lt;p&gt;It's deciding whether that answer deserves to be trusted.&lt;/p&gt;

&lt;p&gt;An AI system can return a convincing explanation, include several source URLs, and still reach a conclusion that the evidence doesn't support.&lt;/p&gt;

&lt;p&gt;That's the problem I've been focusing on.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real URL doesn't make a claim reliable
&lt;/h2&gt;

&lt;p&gt;Consider a research assistant investigating whether a particular customer problem has become more common over the past year.&lt;/p&gt;

&lt;p&gt;It finds several articles discussing the issue.&lt;/p&gt;

&lt;p&gt;At first glance, everything looks fine. The sources exist, the content is relevant, and the model can summarize what it finds.&lt;/p&gt;

&lt;p&gt;But then come the difficult questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When was each article originally published?&lt;/li&gt;
&lt;li&gt;Was the article updated recently, or actually published recently?&lt;/li&gt;
&lt;li&gt;Does the source support the conclusion, or merely mention the topic?&lt;/li&gt;
&lt;li&gt;Are several articles independently reporting the same problem, or repeating one original claim?&lt;/li&gt;
&lt;li&gt;What happens when two sources disagree?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finding relevant information is only the beginning of research.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small example: conflicting publication dates
&lt;/h2&gt;

&lt;p&gt;One of the cases I'm testing involves extracting publication dates from source content.&lt;/p&gt;

&lt;p&gt;Imagine that the same page contains two explicit publication statements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Published on September 20, 2024.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Published on October 15, 2026.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now imagine the system is evaluating whether that page qualifies as recently published on October 18, 2026.&lt;/p&gt;

&lt;p&gt;A naive implementation might select the newer date and classify the page as recent.&lt;/p&gt;

&lt;p&gt;But that would be a dangerous assumption.&lt;/p&gt;

&lt;p&gt;The two dates conflict. Without additional reliable evidence, the system cannot confidently determine the actual publication date.&lt;/p&gt;

&lt;p&gt;The safer result is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;not_determined&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a deliberately constructed test case, not a claim about an actual article.&lt;/p&gt;

&lt;p&gt;The principle matters beyond dates: when the evidence is contradictory, uncertainty should be preserved rather than silently resolved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separating observation from verification
&lt;/h2&gt;

&lt;p&gt;I'm approaching the research engine as a sequence of different responsibilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Source observation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve content and identify potentially useful information, including dates, relevant passages, and links to supporting material.&lt;/p&gt;

&lt;p&gt;At this stage, extracted information is an observation, not a verified fact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Evidence evaluation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Determine what the source actually establishes.&lt;/p&gt;

&lt;p&gt;For example, a customer complaint may demonstrate that one person experienced a problem. It doesn't automatically prove that the problem is widespread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Answer validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before presenting a conclusion, check whether the available evidence supports it.&lt;/p&gt;

&lt;p&gt;If the evidence is insufficient or contradictory, the answer should communicate that limitation.&lt;/p&gt;

&lt;p&gt;These are design goals I'm working toward, not a claim that the entire research workflow is already solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next question I'm exploring
&lt;/h2&gt;

&lt;p&gt;A suggestion from a recent founder discussion gave me another useful testing idea.&lt;/p&gt;

&lt;p&gt;Suppose the research engine produces a conclusion supported by three sources.&lt;/p&gt;

&lt;p&gt;Now remove the strongest source.&lt;/p&gt;

&lt;p&gt;Should the conclusion remain unchanged?&lt;/p&gt;

&lt;p&gt;Should confidence decrease?&lt;/p&gt;

&lt;p&gt;Or should the system withdraw the conclusion entirely?&lt;/p&gt;

&lt;p&gt;I think this is a useful way to test whether an AI research system actually depends on its evidence rather than simply generating the same convincing explanation with different citations.&lt;/p&gt;

&lt;p&gt;I haven't established the results of that experiment yet, but it's one I want to investigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm learning
&lt;/h2&gt;

&lt;p&gt;Building an AI research tool is making me appreciate how much work exists between retrieving a source and producing a trustworthy conclusion.&lt;/p&gt;

&lt;p&gt;The hard part isn't always making the AI say more.&lt;/p&gt;

&lt;p&gt;Sometimes it's making the system recognize when the available evidence isn't enough to say anything confidently.&lt;/p&gt;

&lt;p&gt;I'm still working through these problems and testing individual components.&lt;/p&gt;

&lt;p&gt;I'm curious how other developers approach this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When building research agents or RAG systems, how do you test whether a generated conclusion is genuinely supported by its sources?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: This article was drafted with ChatGPT assistance. The date example is an illustrative test case, not a production benchmark.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>discuss</category>
    </item>
    <item>
      <title>My background job failed silently for days. Here's how I catch it now.</title>
      <dc:creator>Krasimir Petkov</dc:creator>
      <pubDate>Sat, 02 May 2026 17:42:41 +0000</pubDate>
      <link>https://dev.to/krasimir_petkov_c14f3b461/how-to-monitor-cron-jobs-so-they-dont-fail-silently-2a1f</link>
      <guid>https://dev.to/krasimir_petkov_c14f3b461/how-to-monitor-cron-jobs-so-they-dont-fail-silently-2a1f</guid>
      <description>&lt;p&gt;I found out one of my background jobs had stopped running only after the data looked wrong the next day.&lt;/p&gt;

&lt;p&gt;There was no dramatic crash. No big incident. The job just quietly failed, and I only noticed because something downstream looked stale.&lt;/p&gt;

&lt;p&gt;That is the annoying part about cron jobs and scheduled scripts. Most of the time they run in the background, write some logs, and nobody thinks about them until something is missing.&lt;/p&gt;

&lt;p&gt;I have a few jobs like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data updates&lt;/li&gt;
&lt;li&gt;cleanup scripts&lt;/li&gt;
&lt;li&gt;small imports&lt;/li&gt;
&lt;li&gt;external API calls&lt;/li&gt;
&lt;li&gt;recurring background tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of them are very exciting. But when one of them does not run, or starts and never finishes, it can create a surprisingly annoying problem.&lt;/p&gt;

&lt;p&gt;That is the kind of failure I wanted to make more visible.&lt;/p&gt;

&lt;p&gt;I also built a small V1 of this idea here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://missedrun.com" rel="noopener noreferrer"&gt;https://missedrun.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also a self-hosted version for people who prefer to run this kind of monitoring on their own infrastructure:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/missedrun" rel="noopener noreferrer"&gt;
        missedrun
      &lt;/a&gt; / &lt;a href="https://github.com/missedrun/missedrun-selfhosted" rel="noopener noreferrer"&gt;
        missedrun-selfhosted
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Self-hosted cron job monitoring with ping URLs and email alerts.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;MissedRun Self-hosted&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Self-hosted cron and scheduled job monitoring for detecting silent failures.&lt;/p&gt;
&lt;p&gt;MissedRun monitors recurring jobs such as cron scripts, backups, imports, ETL pipelines, billing syncs, cleanup tasks, and scheduled reports.&lt;/p&gt;
&lt;p&gt;It works by giving each monitor a unique ping URL. Your job calls that URL when it runs, starts, finishes successfully, or fails. If the job does not check in within the expected interval plus grace period, MissedRun marks it as missing and can send an alert.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hosted version: &lt;a href="https://missedrun.com" rel="nofollow noopener noreferrer"&gt;https://missedrun.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Self-hosted version: &lt;a href="https://github.com/missedrun/missedrun-selfhosted" rel="noopener noreferrer"&gt;https://github.com/missedrun/missedrun-selfhosted&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;License: AGPL-3.0&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What problem does it solve?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Some production failures are not loud.&lt;/p&gt;
&lt;p&gt;A job can stop running without throwing an exception. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cron did not run&lt;/li&gt;
&lt;li&gt;the server was down&lt;/li&gt;
&lt;li&gt;a Docker container stopped&lt;/li&gt;
&lt;li&gt;credentials expired before the job reached your alerting code&lt;/li&gt;
&lt;li&gt;a backup script never started&lt;/li&gt;
&lt;li&gt;an import stopped updating data&lt;/li&gt;
&lt;li&gt;a scheduled report was not generated&lt;/li&gt;
&lt;li&gt;a background worker silently stopped&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/missedrun/missedrun-selfhosted" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This is not a big launch. I am mostly trying to understand if this is a real enough problem for other developers who run cron jobs, ETL jobs, backups, imports, cleanup scripts, or other scheduled tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Cron jobs are easy to forget about.&lt;/p&gt;

&lt;p&gt;They usually do not have a UI. They run somewhere on a server, maybe write logs, and then disappear into the background.&lt;/p&gt;

&lt;p&gt;A job can fail because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an API token expired&lt;/li&gt;
&lt;li&gt;an environment variable is missing&lt;/li&gt;
&lt;li&gt;a database connection failed&lt;/li&gt;
&lt;li&gt;the server restarted&lt;/li&gt;
&lt;li&gt;the script crashed&lt;/li&gt;
&lt;li&gt;the job started but never finished&lt;/li&gt;
&lt;li&gt;the cron entry was changed or removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logs are useful, but only if you go and check them.&lt;/p&gt;

&lt;p&gt;In practice, I usually only check logs after I already suspect something is broken.&lt;/p&gt;

&lt;p&gt;For recurring jobs, I often want a much simpler answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;did it start?&lt;/li&gt;
&lt;li&gt;did it finish?&lt;/li&gt;
&lt;li&gt;did it fail?&lt;/li&gt;
&lt;li&gt;did it miss the expected time?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The ping approach
&lt;/h2&gt;

&lt;p&gt;One simple way to monitor this is to make the job report its own status.&lt;/p&gt;

&lt;p&gt;The basic pattern is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;send a start ping when the job begins&lt;/li&gt;
&lt;li&gt;send a success ping when it finishes&lt;/li&gt;
&lt;li&gt;send a failure ping if it crashes&lt;/li&gt;
&lt;li&gt;mark it as late or missed if the expected ping does not arrive&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is not a complicated idea, but I have found it very useful in practice.&lt;/p&gt;

&lt;p&gt;Instead of checking logs manually, the job tells you whether it is still alive.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if the start ping arrives, the job is running&lt;/li&gt;
&lt;li&gt;if the success ping arrives, the job finished&lt;/li&gt;
&lt;li&gt;if the fail ping arrives, the job crashed&lt;/li&gt;
&lt;li&gt;if nothing arrives when expected, the job is late or missed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last case is the important one for me.&lt;/p&gt;

&lt;p&gt;A lot of failures are not loud. The job does not always send an error. Sometimes it just does not run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bash example
&lt;/h2&gt;

&lt;p&gt;Here is a simple shell wrapper.&lt;/p&gt;

&lt;p&gt;This uses placeholder URLs. In a real setup, these would be the ping URLs generated by your monitoring tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;START_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/ping/YOUR_TOKEN/start"&lt;/span&gt;
&lt;span class="nv"&gt;SUCCESS_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/ping/YOUR_TOKEN"&lt;/span&gt;
&lt;span class="nv"&gt;FAIL_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/ping/YOUR_TOKEN/fail"&lt;/span&gt;

curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;--max-time&lt;/span&gt; 5 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$START_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true

&lt;/span&gt;your-real-command-here

&lt;span class="nv"&gt;EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$EXIT_CODE&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;--max-time&lt;/span&gt; 5 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SUCCESS_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="k"&gt;else
  &lt;/span&gt;curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;--max-time&lt;/span&gt; 5 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FAIL_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nv"&gt;$EXIT_CODE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful links
&lt;/h2&gt;

&lt;p&gt;I also wrote a few short pages around the specific cases I keep running into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cron job monitoring guide: &lt;a href="https://missedrun.com/cron-job-monitoring" rel="noopener noreferrer"&gt;https://missedrun.com/cron-job-monitoring&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Detect missed cron jobs: &lt;a href="https://missedrun.com/missed-cron-job" rel="noopener noreferrer"&gt;https://missedrun.com/missed-cron-job&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Self-hosted cron monitoring: &lt;a href="https://missedrun.com/self-hosted-cron-monitoring" rel="noopener noreferrer"&gt;https://missedrun.com/self-hosted-cron-monitoring&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>monitoring</category>
      <category>devops</category>
      <category>automation</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>Building a Real-Time Stock Scanner with Redis, WebSockets, and Postgres</title>
      <dc:creator>Krasimir Petkov</dc:creator>
      <pubDate>Thu, 22 Jan 2026 17:32:33 +0000</pubDate>
      <link>https://dev.to/krasimir_petkov_c14f3b461/building-a-real-time-stock-scanner-with-redis-websockets-and-postgres-2ig2</link>
      <guid>https://dev.to/krasimir_petkov_c14f3b461/building-a-real-time-stock-scanner-with-redis-websockets-and-postgres-2ig2</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;This project started as an internal tool to understand unusual volume and intraday activity across thousands of US stocks.&lt;/p&gt;

&lt;p&gt;I recently built a real-time stock scanner that ingests thousands of symbols, processes live updates, and serves them to users with minimal delay. This post is a short breakdown of the architecture decisions that worked (and the ones that didn’t).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;Market data is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;high-frequency&lt;/li&gt;
&lt;li&gt;bursty&lt;/li&gt;
&lt;li&gt;time-sensitive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing every update directly to a relational database quickly becomes expensive and unnecessary — especially when most of the data is only relevant for seconds or minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The system is split into three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ingestion&lt;/strong&gt; — pulling snapshot and streaming data from external APIs
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processing&lt;/strong&gt; — normalizing, filtering, and calculating derived metrics
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution&lt;/strong&gt; — pushing live updates to the frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a high level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis handles hot, ephemeral data&lt;/li&gt;
&lt;li&gt;Postgres stores validated, historical data&lt;/li&gt;
&lt;li&gt;WebSockets deliver updates to clients in real time&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Redis for Live Data
&lt;/h2&gt;

&lt;p&gt;Redis turned out to be a much better fit than Postgres for intraday updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In-memory speed&lt;/li&gt;
&lt;li&gt;Natural TTL support for expiring symbols&lt;/li&gt;
&lt;li&gt;Pub/Sub for fan-out&lt;/li&gt;
&lt;li&gt;Zero WAL / IO pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Postgres is still excellent — just not for data that changes every few seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  WebSockets for Distribution
&lt;/h2&gt;

&lt;p&gt;Instead of polling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;active symbols are tracked dynamically&lt;/li&gt;
&lt;li&gt;only “in-play” tickers receive updates&lt;/li&gt;
&lt;li&gt;clients subscribe to exactly what they need&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps both bandwidth and server load under control.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I’d Do Differently Next Time
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Separate “hot” and “cold” data earlier&lt;/li&gt;
&lt;li&gt;Treat intraday data as disposable by default&lt;/li&gt;
&lt;li&gt;Avoid over-modeling early — schemas can come later&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Live Demo
&lt;/h2&gt;

&lt;p&gt;The project is live here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://zipston.com" rel="noopener noreferrer"&gt;https://zipston.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s still evolving, but the core real-time pipeline is already doing the heavy lifting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Real-time systems are less about frameworks and more about respecting the nature of your data.&lt;/p&gt;

&lt;p&gt;If your data expires quickly, your architecture should too.&lt;br&gt;
Happy to answer questions or discuss real-time data tradeoffs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
