<?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: Outfame Team</title>
    <description>The latest articles on DEV Community by Outfame Team (@outfame).</description>
    <link>https://dev.to/outfame</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%2F4221405%2F3652f5dc-b6d5-4bf2-beb3-ab8ffc30875f.png</url>
      <title>DEV Community: Outfame Team</title>
      <link>https://dev.to/outfame</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/outfame"/>
    <language>en</language>
    <item>
      <title>5 rules we used to turn 164,963 daily follower readings into one honest growth number</title>
      <dc:creator>Outfame Team</dc:creator>
      <pubDate>Mon, 02 Nov 2026 02:51:23 +0000</pubDate>
      <link>https://dev.to/outfame/5-rules-we-used-to-turn-164963-daily-follower-readings-into-one-honest-growth-number-3kpa</link>
      <guid>https://dev.to/outfame/5-rules-we-used-to-turn-164963-daily-follower-readings-into-one-honest-growth-number-3kpa</guid>
      <description>&lt;p&gt;We publish an &lt;a href="https://www.outfame.com/instagram-growth-statistics" rel="noopener noreferrer"&gt;Instagram growth statistics page&lt;/a&gt; built from our own customer data: 164,963 daily follower-count readings from 7,271 Instagram accounts. The headline result is a median gain of +346 followers in the first 30 days across 981 accounts, with 86% of them growing. Below are the five cleaning rules that produced that number, why each one exists, and a SQL sketch of the core query.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Measure at "the reading closest to day N", within a window
&lt;/h2&gt;

&lt;p&gt;Daily readings are not perfectly daily. A job fails, an account is private for a day, a request times out. So the gain at day 30 is the reading closest to day 30, as long as it falls within 3 days of it, minus the first reading. Same rule for day 60 and day 90.&lt;/p&gt;

&lt;p&gt;Without a window you either lose most accounts (an exact day-30 reading is often missing) or you silently mix day-24 and day-37 readings into one "30-day" number.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Only count accounts that are still being measured on that day
&lt;/h2&gt;

&lt;p&gt;An account counts toward the day-30 figure only if it still has a reading on day 30. That is why the sample shrinks over time: 981 accounts at day 30, 577 at day 60, 417 at day 90.&lt;/p&gt;

&lt;p&gt;This is a survivor-only number, and the page says so: each figure describes accounts that were still running on that day. Mixing survivors and drop-outs into one denominator would look tidier and mean less.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Use medians, not means
&lt;/h2&gt;

&lt;p&gt;A handful of very large accounts would dominate an average. The median of +346 sits next to an interquartile range of +73 to +549 on the page, which tells you more about the spread than a mean ever would. Accounts over 100,000 followers were left out of the size breakdown entirely: too few were measured and their results varied too widely for a reliable median.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Drop impossible jumps
&lt;/h2&gt;

&lt;p&gt;394 accounts were excluded because the follower count jumped above 5x or fell below one fifth of the starting count. In practice that is almost always a changed username (the tracker starts reading a different account) or a failed reading that returned a wrong number. A single rule catches both without hand-labelling anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Cut off data you cannot trust yet
&lt;/h2&gt;

&lt;p&gt;Accounts that started from June 2026 on are not included yet. Too many of their daily readings repeat the previous day's count exactly, which we treat as a stale reading rather than zero growth. Publishing those months would have pulled the median down for a measurement reason, not a growth reason. They will be added once those months can be measured properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  A SQL sketch of the day-30 query
&lt;/h2&gt;

&lt;p&gt;This is a simplified sketch of the approach in Postgres, not production code. &lt;code&gt;readings&lt;/code&gt; holds one row per account per reading.&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;with&lt;/span&gt; &lt;span class="n"&gt;first_reading&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read_on&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;start_day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;followers&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;start_followers&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;readings&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;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;read_on&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;day30&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;readings&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
  &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;first_reading&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_on&lt;/span&gt; &lt;span class="k"&gt;between&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_day&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_day&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;   &lt;span class="c1"&gt;-- within 3 days of day 30&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;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_on&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;-- closest reading wins&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;gains&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_followers&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;nullif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_followers&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="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ratio&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day30&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
  &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;first_reading&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                             &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;percentile_cont&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;within&lt;/span&gt; &lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="p"&gt;(&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;gain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;median_gain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;gain&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                                 &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;share_grew&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gains&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;ratio&lt;/span&gt; &lt;span class="k"&gt;between&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;-- drop impossible jumps (the real filter checks every reading)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the cleaned data showed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Median gain: +346 at day 30, +483 at day 60, +533 at day 90.&lt;/li&gt;
&lt;li&gt;Growth is front-loaded: the typical account that grew over 90 days had made 62% of that gain by day 30 (264 accounts).&lt;/li&gt;
&lt;li&gt;Starting size changes the percentage far more than the raw number: +341 (+69.4%) for accounts under 1,000 followers, +359 (+12.5%) for 1,000 to 9,999, and +288 (+1.0%) for 10,000 to 99,999.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are results for one service's customers, not a promise for any single account. The full tables, by starting size and by niche, are on the &lt;a href="https://www.outfame.com/instagram-growth-statistics" rel="noopener noreferrer"&gt;statistics page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you measure growth curves from noisy daily snapshots, the two rules that changed our numbers most were the jump filter and the stale-reading cutoff. Both are cheap to add and easy to explain.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>analytics</category>
      <category>sql</category>
      <category>statistics</category>
    </item>
  </channel>
</rss>
