<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Prabodh : Technology]]></title><description><![CDATA[This section explores topics that help you transform ideas into digital reality. You’ll learn how to understand technology in simple, practical ways and use it effectively to achieve the best outcomes. From grasping essential tools to applying smart strategies, the focus is on turning creativity into solutions that work in the real world.]]></description><link>https://blog.prabodh.in/s/technology</link><image><url>https://substackcdn.com/image/fetch/$s_!Vzgs!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F250233d9-169e-4c1d-82f3-23f5ca93ec2e_1280x1280.png</url><title>Prabodh : Technology</title><link>https://blog.prabodh.in/s/technology</link></image><generator>Substack</generator><lastBuildDate>Sat, 01 Aug 2026 08:33:38 GMT</lastBuildDate><atom:link href="https://blog.prabodh.in/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Prabodh Technologies LLP]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[vikasputcha@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[vikasputcha@substack.com]]></itunes:email><itunes:name><![CDATA[Vikas Putcha]]></itunes:name></itunes:owner><itunes:author><![CDATA[Vikas Putcha]]></itunes:author><googleplay:owner><![CDATA[vikasputcha@substack.com]]></googleplay:owner><googleplay:email><![CDATA[vikasputcha@substack.com]]></googleplay:email><googleplay:author><![CDATA[Vikas Putcha]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[XY - Possible usage - My read on it.]]></title><description><![CDATA[A charting library that plots ten billion points &#8212; how it works, what it costs, and when you shouldn&#8217;t use it.]]></description><link>https://blog.prabodh.in/p/xy-possible-usage-my-read-on-it</link><guid isPermaLink="false">https://blog.prabodh.in/p/xy-possible-usage-my-read-on-it</guid><dc:creator><![CDATA[Vikas Putcha]]></dc:creator><pubDate>Sat, 01 Aug 2026 04:39:22 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7e79f078-bada-437b-992c-4de6c061d941_1200x630.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><span>Disclosure</span></strong><span>: </span><em><span>This piece was researched and drafted with Claude, working from the XY source, its design dossier, and its benchmark documentation. Claims were verified locally by creating &amp; running a </span><a href="https://gist.github.com/prabodh-dev1/69e93e6b1968cbdddbb77b868cef84f1"><span>validation script</span></a><span>; the two figures marked [R] are reported by the project's CI and were not independently re-run.</span></em></p><p>XY is an alpha-stage Python charting library aimed at a specific gap: datasets too large for Plotly or Bokeh but where you still want to pan, zoom, hover and click. The claim that drew me in was that its cost is bounded by screen size rather than data size.</p><p>That&#8217;s a testable claim, so I tested it. This post walks through what the design does, what the measurements showed, and where I think it does and doesn&#8217;t belong.</p><p><strong>Who this is written for:</strong> you can read Python, you know what an array is, and you&#8217;ve made a plot with Matplotlib at some point. Everything else is explained.</p><p><strong>Where the numbers come from.</strong> Every figure carries its source:</p><ul><li><p><strong>[M]</strong> &#8212; measured on an Apple Silicon laptop</p></li><li><p><strong>[C]</strong> &#8212; derived from constants in <code>python/xy/config.py</code></p></li><li><p><strong>[R]</strong> &#8212; reported by the project&#8217;s CI benchmarks in <code>spec/benchmarks/results.md</code></p></li></ul><p>The last section covers how to reproduce all of them.</p><div><hr></div><h2>The problem you haven&#8217;t run into yet</h2><p>Most plots are a few hundred points. It feels instant, so you never think about what the library is doing underneath.</p><p>Now imagine a file with ten million rows &#8212; every flight that took off last year, or every star in a sky survey &#8212; and the instruction &#8220;plot it.&#8221;</p><p>The obvious code:</p><p>python</p><pre><code><code>import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.savefig("out.png")</code></code></pre><p>That took about <strong>860 ms and 580 MB of memory [M]</strong>. In Plotly, asking for an interactive chart you can pan and zoom takes <strong>54 seconds and 1.5 GB [R]</strong>. In Plotly&#8217;s default non-GPU mode, which builds one SVG element per point, it never finishes at all &#8212; that path stops being usable somewhere above a million points [R].</p><p>Now look at your screen. A typical plot area is around 1200 &#215; 800 pixels: <strong>960,000 pixels total [M]</strong>. Ten million things drawn onto fewer than a million dots means <strong>10.4 points share each pixel [M]</strong> on average. Nine out of ten are painted over before you ever see them.</p><p>The machine did enormous work to produce an image carrying no more information than a much cheaper image would have.</p><p>That observation is the foundation of XY&#8217;s design.</p><div><hr></div><h2>The core idea</h2><p>Traditional charting libraries have a cost that scales with <strong>how much data you have</strong>. Ten times the data, roughly ten times the work.</p><p>XY is built so cost scales with <strong>how many pixels are on screen</strong>.</p><p>Your screen doesn&#8217;t grow when your dataset does, so past a certain size, plotting more data costs almost nothing extra. The payloads I measured:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/bTkjZ/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7176ca51-6698-4a8c-bfd7-0df7486f429d_1220x260.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6e9f01c4-e888-4765-95af-bc85e4377b61_1220x330.png&quot;,&quot;height&quot;:155,&quot;title&quot;:&quot;Observation from Local run&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/bTkjZ/1/" width="730" height="155" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>Two things there need explaining, and the explanation turned out to be the most interesting part of the exercise.</p><p>First, a 10&#215; jump from one million to ten million changes the payload by <strong>0.7% [M]</strong>. Second &#8212; and this reads like a typo the first time &#8212; plotting <em>more</em> data sent <em>less</em>.</p><p>Nothing shrank. Those rows are two different formats either side of a switch.</p><div><hr></div><h2>One number, two formats</h2><p>XY picks a representation based on how many points are visible. The switch is a constant in <code>python/xy/config.py</code>:</p><p>python</p><pre><code><code>SCATTER_DENSITY_THRESHOLD = 200_000
DENSITY_GRID = (512, 384)
DENSITY_SAMPLE_TARGET = 8_192</code></code></pre><h3>Below the threshold: direct mode</h3><p>Every point ships individually as two 32-bit floats &#8212; an x and a y &#8212; so <strong>8 bytes per point</strong>. 100,000 points is 100,000 &#215; 8 = 800,000 bytes = <strong>781.25 KB [C]</strong>, which is the 782 KB measured above. Cost grows linearly and without limit; ten million points would be 78 MB.</p><p>In exchange, every point is really there. You can hover it, click it, colour it individually.</p><h3>Above the threshold: density mode</h3><p>XY stops sending points and sends a picture of where they were:</p><pre><code><code>count grid      512 &#215; 384 cells &#215; 1 byte  = 196,608 B = 192 KB
sample overlay  8,192 points &#215; 2 &#215; f32    =  65,536 B =  64 KB
                                            &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;
                                                        256 KB  [C]
+ chart specification metadata                           ~3 KB
                                            &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;
                                                        259 KB</code></code></pre><p>Measured: <strong>258&#8211;260 KB [M]</strong>. The derivation agrees to within 3 KB.</p><p>Now notice what&#8217;s <em>missing</em> from that calculation: <strong>N never appears</strong>. The grid is 512 &#215; 384 whether it holds a thousand points or a billion. The sample overlay is 8,192 points regardless. No term in the formula can be influenced by your data size.</p><p>That&#8217;s the difference between &#8220;flat in practice&#8221; and &#8220;flat by construction.&#8221; The payload isn&#8217;t flat because someone optimized carefully &#8212; it&#8217;s flat because the format has no room to be anything else.</p><h3>The gap that reveals the priorities</h3><p>Density mode costs 256 KB. Direct mode costs 8 bytes per point. Set them equal:</p><pre><code><code>256 KB &#247; 8 bytes = 32,768 points  [C]</code></code></pre><p>Above 32,768 points, direct mode is already the more expensive way to send a chart. But XY doesn&#8217;t switch there &#8212; it switches at 200,000, shipping up to <strong>6.1&#215; more data than it strictly needs to [C]</strong> in between.</p><p>That gap is deliberate. The LOD specification states the rule directly:</p><blockquote><p><strong>Invariant L2 (exact under budget):</strong> if <code>visible &#8804; budget</code>, the user sees real marks with real channels &#8212; never a sample, never an aggregate.</p><p>&#8212; <code>spec/design/lod-architecture.md</code></p></blockquote><p>Under the budget you get exact hover, exact selection, and a real colour per mark. A density grid provides none of those. Bandwidth is the cheaper thing to spend, so XY spends it.</p><p><strong>The payload curve is a step function:</strong> linear, then a cliff, then horizontal forever.</p><div><hr></div><h2>What makes it possible</h2><p>The step function is the visible behaviour. Five design decisions underpin it.</p><h3>Numbers travel as bytes, not text</h3><p>When Plotly sends data to the browser, it converts it to JSON:</p><p>json</p><pre><code><code>{"x": [1.0, 2.0, 3.0]}</code></code></pre><p>A double-precision float is 8 bytes in memory. As JSON text, a realistic coordinate like <code>-73.98452301</code> runs a dozen characters; with separators the average worked out to <strong>19.9 bytes per number [M]</strong> &#8212; <strong>5.0&#215; the 4 bytes [M]</strong> the same value occupies as a 32-bit float.</p><p>Size is only half of it. The browser must then <em>parse</em> every one of those strings back into a number, character by character. For twenty million numbers, that&#8217;s hundreds of megabytes of text and a parse that blocks the page.</p><p>XY moves data as raw binary float buffers. The design dossier states it as an invariant:</p><blockquote><p>No JSON numbers on the wire; data moves as raw f32 buffers (&#167;29).</p></blockquote><p>The bytes leaving your NumPy array are byte-for-byte the bytes the graphics card reads. The only copies are <code>memcpy</code>copies &#8212; blind block moves &#8212; never parse-a-number copies.</p><p><strong>Transferable idea:</strong> text is a fine container for configuration and a poor one for data.</p><h3>Computation runs where the data already is</h3><p>Plotly computes in JavaScript, in the browser, on the same thread that handles your clicks. That&#8217;s why pages freeze.</p><p>XY computes in <strong>Rust</strong> &#8212; a compiled language in C&#8217;s performance class &#8212; running <em>inside your Python process</em>. The data never leaves the machine to be processed; the browser receives a finished, small result.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/5WTMB/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1ac7ff0-a18a-4116-9805-ac5fd665f2c6_1220x260.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bac6dbe1-e6b6-42d6-b131-390a52b8a4d6_1220x330.png&quot;,&quot;height&quot;:155,&quot;title&quot;:&quot;Payload-build time for a scatter chart&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/5WTMB/1/" width="730" height="155" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>(The project&#8217;s CI, on slower hardware, records 2 ms at 100,000 points [R].)</p><p><strong>Transferable idea:</strong> move the computation to the data, not the data to the computation. It&#8217;s why databases push filters down to storage.</p><h3>The graphics card draws the marks</h3><p>Plotly&#8217;s default scatter creates one SVG element per point &#8212; a real object in the page&#8217;s document tree, like a <code>&lt;div&gt;</code>, carrying hundreds of bytes of structure and style. Browsers degrade badly past ten to a hundred thousand of them, which is why that path takes 44 seconds at one million points and 113 seconds at three million [R].</p><p>XY draws through <strong>WebGL2</strong>, the browser&#8217;s interface to your GPU (<code>js/src/50_chartview.ts</code>). GPUs exist to run the same small operation on millions of items at once. XY uses <em>instanced rendering</em>: upload one marker shape, then issue a single command meaning &#8220;draw this 500,000 times, at these positions.&#8221;</p><p>The HTML document is still used &#8212; for axis labels, legend and tooltips. Small things, few of them.</p><p>Worth knowing: the GPU holds only a <strong>cache</strong>. Canonical data stays CPU-side in 64-bit precision, and every GPU buffer is droppable and rebuildable. Hover, selection, export and zoom all need the real values, and data that exists only in video memory can&#8217;t serve them.</p><h3>Level of detail</h3><p>The same idea games use: a distant mountain isn&#8217;t rendered rock by rock.</p><p>XY defines four tiers and picks one per chart, re-picking as you zoom (<code>spec/design/lod-architecture.md</code>):</p><p><strong>Tier 0 &#8212; Direct.</strong> Draw every point, exactly. No approximation.</p><p><strong>Tier 1 &#8212; Decimation, for lines.</strong> A stock price with 100 million samples on a 1,200-pixel-wide chart gives each pixel column ~83,000 samples. But a pixel column can only show a vertical segment, so what matters is the <strong>first, last, minimum and maximum</strong> value in that column. Keep four, discard the rest.</p><p>This is the <strong>M4 algorithm</strong> (Jugel et al., VLDB 2014), and its property is unusual: the reduced line rasterizes to an image <em>identical</em> to the full-data line. Not similar &#8212; identical.</p><p>That&#8217;s testable, so the harness tests it. Rasterizing a 2,000,000-point signal with sharp spikes at 1200px wide, both fully and M4-reduced, then comparing every pixel column:</p><pre><code><code>points in:            2,000,000
points kept:              4,777   (419&#215; reduction)   [M]
M4 max deviation:           0.0                      [M]
naive subsampling,
same budget:              302.16                     [M]</code></code></pre><p>Zero. Uniform subsampling to the identical budget misses spikes by 302 units. Same number of points kept; one method is exact and the other isn&#8217;t.</p><p><strong>Tier 2 &#8212; Density surfaces, for scatter.</strong> Scatter points have no order, so dropping some would genuinely distort the picture. Instead XY bins them into the fixed grid described above.</p><p><strong>Tier 3 &#8212; Out-of-core tiles.</strong> Beyond RAM, canonical data stays on disk and only the tiles the current view needs are read &#8212; the way map applications load tiles as you pan.</p><h3>A floating-point trap worth remembering</h3><p>This one will show up in your own code someday.</p><p>GPUs prefer 32-bit floats over 64-bit &#8212; half the memory, faster to process. So the obvious optimization is storing coordinates as <code>float32</code>.</p><p>A <code>float32</code> has a 24-bit mantissa: about <strong>7 significant decimal digits total</strong> (not 7 after the decimal point).</p><p>Now consider time. Computers commonly store timestamps as milliseconds since 1 January 1970 &#8212; currently around <strong>1,700,000,000,000</strong>, thirteen digits. Seven digits of precision for a thirteen-digit number leaves the last six as noise.</p><p>Measured precisely:</p><pre><code><code>gap between neighbouring float32 values near 1.7e12:
    131,072 ms  =  2 minutes 11 seconds          [M]

a day of per-second readings (86,400 samples):
    660 distinct x-positions survive              [M]</code></code></pre><p>A day of data becomes 660 columns. No exception, no warning &#8212; just a chart that&#8217;s quietly wrong.</p><p><strong>The fix is a change of coordinates, not more bits.</strong> Keep full precision in Python; compute a per-column <strong>offset</strong>; subtract it before the cast:</p><pre><code><code>raw:        1_700_000_000_000, 1_700_000_001_000, 1_700_000_002_000
offset:     1_700_000_001_000
relative:              -1_000,                 0,             1_000</code></code></pre><p>Those small numbers fit a <code>float32</code> with room to spare. The offset stays in Python as a 64-bit value and is added back during rendering. Round-tripping the same timestamps this way gave a <strong>maximum error of 0 ms at 4 bytes per value [M]</strong> &#8212; same storage, exact results. When you zoom far enough that precision tightens again, XY re-centres the offset.</p><p>The technique isn&#8217;t XY&#8217;s invention. deck.gl adopted it and then removed their far more complex emulated-64-bit code, reporting that the offset approach &#8220;rivals 64-bit precision at 32-bit speeds.&#8221; Cesium uses the same idea under the name RTC.</p><p><strong>Transferable idea:</strong> when an optimization looks free, find out what it costs. And when precision fails, ask whether you can move the origin before asking for more bits.</p><div><hr></div><h2>Summarising without distorting</h2><p>Here&#8217;s a question that sounds simple and isn&#8217;t.</p><p>You&#8217;re plotting a million flights, coloured by airline &#8212; red for one, blue for another. Zoomed out, XY is in density mode, and one cell now covers 500 flights of mixed colour.</p><p><strong>What colour is that cell?</strong></p><p>Each obvious answer distorts something:</p><ul><li><p><strong>Colour by count alone</strong> &#8212; the airline information is gone entirely.</p></li><li><p><strong>Majority wins</strong> &#8212; a cell holding 251 red and 249 blue renders as pure red. Minorities vanish.</p></li><li><p><strong>Brightest or maximum</strong> &#8212; one outlier speaks for 500 points.</p></li></ul><p>XY&#8217;s rule, from <code>spec/design/lod-architecture.md</code>:</p><blockquote><p>the density surface wears the data&#8217;s own colors, and it composites like the data&#8217;s own points</p></blockquote><p>Each cell shows the <strong>alpha-weighted mean of its points&#8217; actual colours, averaged in linear light</strong>, and its transparency is set to what that many overlapping semi-transparent marks would physically produce &#8212; <code>1 &#8722; (1 &#8722; a)&#7503;</code> for k points.</p><p>The consequence: the zoomed-out surface and the zoomed-in points are the same image at two magnifications. Zoom in and the surface dissolves into individual marks with the same hue and brightness. Nothing jumps.</p><p>The &#8220;linear light&#8221; detail is doing real work. Screen colours are stored in sRGB, a non-linear encoding matched to human perception. Averaging red and blue as raw bytes gives a <strong>dark purple of 128</strong>; converting to linear light, averaging, then converting back gives <strong>188 [M]</strong> &#8212; which is what overlapping red and blue light actually produces. Both values verified exactly.</p><p>Where a channel has no honest aggregate &#8212; marker <em>size</em> has no meaningful average &#8212; XY drops it and renders a visible &#8220;aggregated&#8221; badge, so a summary can&#8217;t be mistaken for raw data.</p><p>The project&#8217;s own competitive research is candid that most of XY&#8217;s parts exist elsewhere: GPU rendering, binary transport, density aggregation and tile pyramids are all prior art. What it identifies as new is the combination together with these truthfulness rules.</p><div><hr></div><h2>Points that remember where they came from</h2><p>If XY sends a grid instead of points, how do you click a flight and see its callsign?</p><p>The design is <strong>indices, not payloads</strong>. Hover and selection return <strong>row positions into your original data</strong>:</p><p>python</p><pre><code><code>import xy, pandas as pd

flights = pd.read_parquet("flights.parquet")   # 10M rows, 40 columns

def on_select(sel):
    picked = flights.iloc[sel.index]           # full records, all 40 columns
    print(picked.groupby("airline").size())

xy.scatter_chart(
    xy.scatter(x="lon", y="lat", color="airline", size="altitude", data=flights),
    on_select=on_select,
)</code></code></pre><p>Verified: box-selecting a region returned <strong>3,163 indices where a NumPy mask predicted 3,163 &#8212; exact match [M]</strong>.</p><p>The reason for the design is arithmetic. Attaching a 40-byte callsign to each of ten million points would add 400 MB to the wire and dismantle everything above. Row position costs nothing &#8212; it already exists implicitly in array order.</p><p><strong>The GPU knows geometry. Python knows everything. Array position links them.</strong></p><p>One consequence to plan around: in density mode there are no individual points to hover, so you get a cell summary plus a drill to the top rows in that cell. Zoom past the budget and exact per-point hover returns.</p><div><hr></div><h2>Where XY fits</h2><p><strong>Large scientific and engineering data.</strong> Sensor logs, particle physics, sky surveys, genomics &#8212; millions of rows you need to <em>look at</em>, not just compute on.</p><p><strong>Time series and monitoring.</strong> Offset encoding keeps timestamps exact, M4 keeps long histories cheap, and appends cost only the size of the append rather than a full re-send, so live dashboards stay responsive.</p><p><strong>Work that needs points back, not just pixels.</strong> Select a region, get the records. The main alternative for very large scatter plots, <strong>datashader</strong>, returns a finished image &#8212; there&#8217;s nothing to click.</p><p><strong>Ordinary small charts.</strong> XY isn&#8217;t only a big-data tool: 0.4 ms to build a 100,000-point chart [M] against 159 ms for Plotly to serialize the same chart to HTML [M]. Small-data startup is a tracked benchmark category with an explicit goal of beating Plotly, Bokeh and Altair on first paint [R].</p><div><hr></div><h2>Where XY is the wrong tool</h2><p><strong>Games and general graphics.</strong> XY uses the GPU, but nothing about it generalises. It&#8217;s <em>event-driven</em>: it draws when something changes, then goes idle. Games do the opposite &#8212; simulate and draw every frame, continuously. XY&#8217;s central optimization is that panning updates a few GPU variables and never touches data buffers, which is precisely wrong for a world that changes each tick. The mark types are also a fixed set of about twenty; the plugin documentation is explicit that a plugin returns &#8220;ordinary XY marks &#8212; <em>not shaders, not draw calls</em>.&#8221; That restriction is what lets plugins inherit hover, selection and export for free, but custom geometry needs a different tool. Use PixiJS or Three.js on the web, Godot or Unity natively.</p><p><strong>Native mobile apps.</strong> The Rust engine runs inside a Python process. Phones don&#8217;t have one. A browser-embeddable bundle exists and would work in a WebView, and a browser-free Rust rasterizer can produce PNGs server-side, but iOS and Android aren&#8217;t supported targets.</p><p><strong>Charts XY doesn&#8217;t have yet.</strong> Plotly ships around forty trace types; XY has scatter, line, area, bar, histogram, box, violin, hexbin, heatmap, contour, error bars and a handful more. Absent: treemap, sunburst, Sankey, radar, gauge, waterfall, funnel &#8212; and <strong>candlestick/OHLC</strong>, which was prototyped on a branch whose pull request was closed unmerged.</p><p>For candlesticks today, <strong>TradingView&#8217;s Lightweight Charts</strong> is the strongest free option &#8212; candlesticks, time axis, crosshairs, price scales and volume panes in about 35 KB, purpose-built for finance rather than bolted on. It&#8217;s JavaScript;<code>lightweight-charts-python</code> wraps it. For a static image in a report, <code>mplfinance</code> is simplest.</p><p>There&#8217;s an elegant footnote there. Candlestick reduction is first/max/min/last per pixel column &#8212; exactly the M4 algorithm XY already ships for lines. And for candles that reduction isn&#8217;t even an approximation: merging sixty one-minute candles into one hourly candle is just a coarser candle, lossless in the chart&#8217;s own language. The architecture suits OHLC unusually well; the mark simply hasn&#8217;t been built.</p><p>The ordering looks deliberate rather than accidental. The shared primitives &#8212; rectangles, filled polygons, grid textures &#8212; came first, because once those exist each new chart type is largely wiring. Breadth is cheap after depth.</p><p><strong>Anything small and routine.</strong> With 5,000 points, XY offers nothing Matplotlib doesn&#8217;t, and Matplotlib is twenty years mature, installed everywhere, and thoroughly documented by strangers who hit your problem first.</p><p><strong>XY is in alpha.</strong> Its design dossier maintains a public list of unresolved issues: the tier decision doesn&#8217;t yet account for GPU fill rate, logarithmic axes skip the tile pyramid and take a full rescan, brightness can shift when zooming certain coloured surfaces. Documented openly &#8212; but this is a project under active construction, not a settled dependency.</p><div><hr></div><h2>Reproducing these numbers</h2><p>Everything marked <strong>[M]</strong> comes from <code>scripts/validate_article_claims.py</code> in the repository. It checks each claim against the value asserted here and prints PASS or FAIL, exiting non-zero on failure so it can run in CI:</p><p>bash</p><pre><code><code>python3 scripts/validate_article_claims.py --sizes 1e5,1e6,1e7</code></code></pre><p>The checks come in three tiers. <strong>Tier A</strong> is arithmetic and needs only NumPy &#8212; the float32 timestamp collapse, the offset-encoding round trip, the linear-light colour figures, the M4 pixel comparison, and the payload derivation read from<code>config.py</code>. <strong>Tier B</strong> exercises the engine and needs the native Rust core (<code>cargo build --release</code>). <strong>Tier C</strong> runs Matplotlib and Plotly for comparison and skips gracefully if they aren&#8217;t installed.</p><p>Two habits came out of building it that I&#8217;d carry to any measurement work.</p><p><strong>Pin the value, not just the trend.</strong> An early version of the payload check verified only that the payload didn&#8217;t grow with N. It passed &#8212; while the figure it was being compared against was three times too large, because that figure came from a benchmark table predating a compression change. A test that checks a trend without pinning the value will certify a wrong number without complaint. The check now asserts flatness <em>and</em> an absolute band, independently.</p><p><strong>Benchmark numbers carry a date.</strong> <code>spec/benchmarks/results.md</code> labels its retained tables with the run that produced them and marks superseded figures explicitly. Reading that metadata is part of reading the number.</p><p>Two figures here are marked <strong>[R]</strong> and weren&#8217;t re-measured locally: Plotly&#8217;s 54 seconds and 1.5 GB at ten million points, and the SVG-path collapse timings. They&#8217;re consistent with the smaller measurements I did take, but they&#8217;re labelled as reported rather than measured because that&#8217;s what they are.</p><p>That labelling habit is one the project itself follows &#8212; its design dossier flags its own &#8220;Plotly uses 40&#8211;100 bytes per point&#8221; figure as an estimate pending measurement rather than publishing it as fact.</p><div><hr></div><h2>What I&#8217;d carry away</h2><p>Four ideas here outlive this particular library.</p><p><strong>Bound the work by the output, not the input.</strong> The screen holds a million pixels. That&#8217;s the real budget. Any system with a fixed-size output has a similar bound available, and most don&#8217;t take it.</p><p><strong>Text is a poor container for numbers.</strong> 19.9 bytes versus 4, plus a parse on the receiving end. Binary formats aren&#8217;t premature optimization at scale; they&#8217;re the difference between working and not.</p><p><strong>Move computation to the data.</strong> Rust inside the Python process rather than JavaScript in the browser. The fastest network request is the one never made.</p><p><strong>The naive optimization is often silently wrong.</strong> &#8220;Use float32, it&#8217;s smaller&#8221; turns a day of per-second data into 660 columns with no error raised. The fix wasn&#8217;t more precision &#8212; it was moving the origin so the numbers got small.</p><p>And one worth stealing from how the project documents itself: XY publishes a list of its own unsolved problems, marks unverified claims as estimates, and credits the prior work each idea came from. That practice is rarer, and more useful, than any technique above.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/WWly8/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd63b4da-3611-4d88-b3c5-bf6309f2d84d_1220x896.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4b2e8c9-b602-4e0c-869d-9f390ce64ea5_1220x966.png&quot;,&quot;height&quot;:473,&quot;title&quot;:&quot;Quick reference&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/WWly8/1/" width="730" height="473" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h2>Sources</h2><ul><li><p><code>spec/design-dossier.md</code> &#8212; architecture, invariants, competitive research</p></li><li><p><code>spec/design/lod-architecture.md</code> &#8212; tier ladder, aggregation truthfulness rules</p></li><li><p><code>spec/benchmarks/results.md</code> &#8212; CI benchmark methodology and results</p></li><li><p><code>python/xy/config.py</code> &#8212; tuning constants used in the payload derivations</p></li><li><p><code>scripts/validate_article_claims.py</code> &#8212; the verification harness</p></li><li><p>Jugel et al., <em>M4: A Visualization-Oriented Time Series Data Aggregation</em>, VLDB 2014</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Understanding HTTP/1.1, 2, and 3]]></title><description><![CDATA[The Hidden Highway of Modern Apps]]></description><link>https://blog.prabodh.in/p/understanding-http11-2-and-3</link><guid isPermaLink="false">https://blog.prabodh.in/p/understanding-http11-2-and-3</guid><dc:creator><![CDATA[Jitendra]]></dc:creator><pubDate>Thu, 09 Oct 2025 03:30:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!SECe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The web protocols that quietly power every React or mobile app carry decades of engineering trade-offs &#8212; from TCP ordering to QUIC stream independence.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SECe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SECe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!SECe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!SECe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!SECe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SECe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213488,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/175450640?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SECe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!SECe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!SECe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!SECe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14fc562b-349d-4e62-90df-6f5a22cc04e7_1536x1024.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This article explores that evolution in depth: how HTTP/1.1, 2, and 3 differ, what they mean for back-end and front-end developers, and how platforms like Nginx, Vercel, and Cloudflare bring it all together.</p><p><strong>Settle in &#8212; this article is not a quick read, but it gathers the detail that turns &#8220;black-box performance&#8221; into predictable engineering.</strong></p><p>When your React or React Native app loads, hundreds of packets race across networks governed by invisible rules &#8212; HTTP versions. Each upgrade &#8212; from <strong>HTTP/1.1</strong> to <strong>HTTP/2</strong> to <strong>HTTP/3</strong> &#8212; reshaped how browsers, servers, and frameworks communicate.<br>Understanding these layers helps developers build faster, safer, and more resilient applications.</p><h2>Why Protocol Versions Still Matter</h2><p>Modern frameworks (Next.js, Remix, Astro, Expo) handle a lot for you, but protocol behavior still affects:</p><ul><li><p>Latency on first load and during navigations</p></li><li><p>Tail performance (p95/p99) under packet loss or mobile transitions</p></li><li><p>Concurrency of module, font, image, API, and streaming fetches</p></li><li><p>Security posture (TLS 1.3, replay risks, Zero&#8209;Trust hops)</p></li><li><p>Observability and capacity planning</p></li></ul><h2>Layer Refresher (Mental Model)</h2><ul><li><p><strong>Application Layer:</strong> Defines HTTP request/response meaning (methods, headers, bodies) and stays stateless per request.</p></li><li><p><strong>Transport Layer:</strong> Moves bytes reliably (TCP) or via independent encrypted streams (QUIC over UDP).</p></li><li><p><strong>Encryption</strong>: TLS 1.2/1.3 secures data above TCP; QUIC bakes TLS 1.3 directly into transport.</p></li><li><p><strong>Multiplexing</strong>: Multiple logical streams share one connection (HTTP/2 on TCP; HTTP/3 on QUIC without cross-stream blocking).</p></li></ul><p><strong>Analogy:</strong><br><strong>HTTP</strong> defines the message.<br><strong>TCP</strong> insists every letter arrive strictly in order.<br><strong>QUIC</strong> lets each envelope arrive independently&#8212;no one waits for the slowest.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/4Qdz6/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/43148bfe-e94e-48e4-af5b-e5720dab98cc_1220x626.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a95e0908-8e8d-44c6-bf8e-6b7c7f15b002_1220x696.png&quot;,&quot;height&quot;:256,&quot;title&quot;:&quot;HTTP Evolution in Context&quot;,&quot;description&quot;:&quot;Create interactive, responsive &amp; beautiful charts &#8212; no code required.&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/4Qdz6/1/" width="730" height="256" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><div><hr></div><h2>HTTP/1.1 &#8212; in a modern web environment</h2><p>HTTP/1.1 powered the early web. It introduced </p><ul><li><p>persistent connections </p></li><li><p>Chunked transfer encoding</p></li><li><p>Basic caching semantics enhancements</p></li></ul><p>but every request still traveled over a single, ordered TCP stream.</p><p>When packet #5 was delayed, packets #6&#8211;#100 waited behind it.<br>This created one of the web&#8217;s earliest bottlenecks: <strong>Head-of-Line Blocking (HOLB).</strong></p><h3>Deep Dive: HTTP is Stateless, but HOLB Isn&#8217;t</h3><p>A common question is:</p><blockquote><p>&#8220;If <strong>HTTP</strong> is stateless, why does one delayed packet stall everything?&#8221;</p></blockquote><p>Here&#8217;s the distinction:</p><ul><li><p><strong>HTTP</strong> lives at the <strong>application layer</strong> &#8212; defining <em>what</em> data is exchanged (<code>GET</code>, <code>POST</code>, headers, body). It&#8217;s <strong>stateless</strong>because each request carries all needed context and doesn&#8217;t depend on earlier ones.</p></li><li><p><strong>HOLB</strong> lives at the <strong>transport layer (TCP)</strong> &#8212; which guarantees ordered delivery of packets. If a packet is lost, the entire stream waits until it&#8217;s retransmitted.</p></li></ul><blockquote><p>The <strong>transport layer</strong> decides <em>how</em> data travels &#8212; handling delivery, ordering, and error correction between endpoints.</p></blockquote><p>So while <strong>HTTP</strong> doesn&#8217;t maintain conversation state, the underlying TCP connection <strong>does maintain ordering state</strong>. That&#8217;s what causes global delays.</p><div><hr></div><h2>HTTP/2 &#8212; Multiplexing and Compression, But Transport HOLB Remains</h2><p><strong>HTTP/2</strong> reimagined how data flows over the same TCP base, bringing four key upgrades:</p><ol><li><p><strong>Binary framing</strong> &#8212; Requests/responses are split into structured frames for faster parsing.</p></li><li><p><strong>Multiplexing</strong> &#8212; Multiple requests share one connection via independent streams.</p></li><li><p><strong>HPACK header compression</strong> &#8212; Repeated headers like cookies are encoded as dictionary references.</p></li><li><p><strong>Server Push(Deprecated in Practice)</strong> &#8212; Servers can pre-send assets they expect the client would need.</p></li></ol><p>What Improved:</p><ul><li><p>Eliminated application-layer HOLB (no strict request sequencing).</p></li><li><p>Fewer TLS handshakes; better use of a single congestion window.</p></li><li><p>Significant header byte reduction for chatty APIs or GraphQL endpoints.</p></li></ul><p>What Didn&#8217;t:</p><ul><li><p><strong>Transport-level HOLB remains.</strong> One lost TCP packet still stalls delivery of frames for all streams sharing that TCP connection until retransmission completes.</p></li></ul><p>Why Server Push Fell Away:</p><ul><li><p>Complexity in correctness (over-pushing/waste).</p></li><li><p>Hard to cache predictably.</p></li><li><p>Browsers (e.g., Chrome, Firefox) disabled or deprecated it. Use instead: <code>rel=preload</code>, <code>rel=preconnect</code>, HTTP 103 Early Hints.</p></li></ul><div><hr></div><h2>&#128272; TLS 1.3, ALPN, and Edge Termination</h2><p>Modern HTTP effectively means <strong>HTTPS</strong>.</p><h4><strong>TLS 1.3:</strong></h4><ul><li><p>Fewer round trips (1-RTT; 0-RTT possible on resumption).</p></li><li><p>Forward secrecy enforced.</p></li><li><p>Cleaner cipher suite landscape.</p></li></ul><h4><strong>ALPN (Application-Layer Protocol Negotiation):</strong></h4><ul><li><p>Client offers: <code>h2, h3, http/1.1</code>.</p></li><li><p>Server picks the highest mutually supported (e.g., <code>h2</code> or <code>h3</code>).</p></li></ul><h4>TLS Termination at the Edge</h4><p>On platforms like <strong>Vercel</strong>, <strong>Cloudflare</strong>, and <strong>Netlify</strong>, TLS usually <strong>terminates at their edge</strong>:</p><ul><li><p>Browser &#8596; Edge: Encrypted (TLS 1.3).</p></li><li><p>Edge &#8596; Your Backend: Often re-encrypted with HTTPS, sometimes proxied via HTTP for internal performance.</p></li><li><p>Frameworks such as Express or Django must use <strong>trust proxy headers</strong> (<code>X-Forwarded-Proto</code>, <code>Host</code>, <code>For</code>) to interpret the original connection as secure.</p></li></ul><blockquote><p><strong>Vercel note:</strong><br>Serverless functions on Vercel run within the same TLS-terminated environment. You don&#8217;t manage certificates &#8212; the edge fabric handles TLS 1.3 automatically.</p></blockquote><p>For self-hosting, Nginx or <a href="https://caddyserver.com">Caddy</a> can terminate TLS and optionally re-encrypt upstream traffic using HTTPS or mTLS &#8212; aligning with <strong>Zero-Trust principles</strong> (&#8220;verify and encrypt every hop&#8221;).</p><div><hr></div><h2>HTTP/3 &#8212; QUIC: Stream Independence &amp; Mobility</h2><p><strong>QUIC(<a href="https://datatracker.ietf.org/doc/html/rfc9000">RFC 9000</a>)</strong> stands for <strong>Quick UDP Internet Connections</strong> &#8212; a transport protocol that blends reliability, encryption, and parallelism on top of UDP.</p><h4>Key Concepts</h4><ul><li><p><strong>0-RTT (Zero Round-Trip Time):</strong> Clients reuse keys from previous sessions to send data immediately without a handshake. Great for mobile users reconnecting frequently.</p></li><li><p><strong>Stream Independence:</strong> Each stream has its own packet numbering and flow control. Packet loss affects only that stream &#8212; others continue unaffected.</p></li><li><p><strong>Connection Migration:</strong> Sessions are tied to a <em>connection ID</em> rather than an IP address. If a device switches from Wi-Fi to 4G, the same connection continues.</p></li><li><p><strong>Built-in TLS 1.3:</strong> Encryption is mandatory and integrated into the transport layer.</p></li><li><p><strong>Header Compression:</strong> <strong>QPACK</strong> (not HPACK). Designed to avoid introducing head-of-line blocking during header table synchronization in a loss scenario.</p></li></ul><h4>Performance Gains:</h4><ul><li><p>Improved tail latency on lossy, mobile, or high-jitter networks.</p></li><li><p>Faster recovery from packet loss; unaffected streams continue.</p></li><li><p>Reduced handshake overhead (esp. with resumption).</p></li></ul><h4>Adoption:</h4><ul><li><p>Major CDNs and browsers widely support HTTP/3.</p></li><li><p><strong>gRPC over HTTP/3</strong>, and is supported by some of the languages</p><ul><li><p><strong>Go / Rust</strong>: Strong HTTP/3 + QUIC libraries.</p></li><li><p><strong>Node.js</strong>: Experimental / progressing; see <a href="https://github.com/nodejs/node/issues/57281">Node.js issue #57281</a>.</p></li><li><p><strong>Python</strong>: User-space libs (<code>aioquic</code>) or via edge proxies (Caddy, Cloudflare) rather than stdlib.</p></li><li><p><strong>Java / .NET</strong>: HTTP/3 adoption moving through library layers (Netty, Jetty, Kestrel updates)., </p></li></ul></li></ul><div><hr></div><h2>Practical Impact by Role</h2><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/S8T16/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c27b8293-ad34-4d99-bfbc-95bdbd7c71e9_1220x632.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6645463a-0169-40de-b9f7-87ae4b62ad7b_1220x702.png&quot;,&quot;height&quot;:277,&quot;title&quot;:&quot;Web Developer Perspective&quot;,&quot;description&quot;:&quot;Create interactive, responsive &amp; beautiful charts &#8212; no code required.&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/S8T16/2/" width="730" height="277" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h3>Frontend / Web App Engineers</h3><ul><li><p>Don&#8217;t over-bundle solely to reduce request count (HTTP/2+ handles concurrency). Still bundle for code splitting strategy and caching boundaries.</p></li><li><p>Use <code>rel=preload</code> (critical CSS, fonts), <code>rel=preconnect</code> (third-party origins), and <code>rel=dns-prefetch</code>.</p></li><li><p>Prefer Early Hints (103) when supported to prime fetches earlier.</p></li><li><p>Eliminate bloat: large cookies and verbose headers consume compression tables.</p></li><li><p>Measure p95 Resource Timing vs just &#8220;Time to First Byte.&#8221;</p></li></ul><h3>React Native / Mobile Clients</h3><ul><li><p>HTTP/3 improves resilience when radios churn (Wi&#8209;Fi &#8596; 4G).</p></li><li><p>Use keep-alive pools carefully; minimize forced connection churn.</p></li><li><p>Monitor tail API latencies under network transitions (simulate with network link conditioners).</p></li></ul><h3>Backend / API Engineers</h3><ul><li><p>Reduce header entropy (avoid ever-growing dynamic data in headers) to maximize HPACK/QPACK efficiency.</p></li><li><p>Validate proxies preserve <code>:authority</code> and correct scheme for downstream auth logic.</p></li><li><p>Tune HTTP/2 max concurrent streams and flow windows if using high-volume streaming (gRPC).</p></li></ul><h3>Infra / Platform</h3><ul><li><p>Roll out HTTP/3 via CDN toggle first&#8212;low risk.</p></li><li><p>Track metrics: loss %, retransmissions, handshake times, p95 vs p99 request latency segments.</p></li><li><p>Consider mTLS for internal re-encryption; align with Zero-Trust.</p></li><li><p>Use Alt-Svc headers to advertise HTTP/3 (<code>Alt-Svc: h3=&#8221;:443&#8221;; ma=86400</code>).</p></li></ul><p></p><div><hr></div><h2>How to Inspect Which Protocol You&#8217;re Using</h2><p>Browser DevTools:</p><ol><li><p>Open Network panel &gt; right-click column header &gt; enable &#8220;Protocol&#8221;.</p></li><li><p>Reload &#8212; look for <code>h2</code>, <code>h3</code>, or <code>http/1.1</code></p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BeJK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BeJK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 424w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 848w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BeJK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png" width="1456" height="518" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:518,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:689836,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/175450640?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BeJK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 424w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 848w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!BeJK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc86a1a17-cb94-4d5e-b28d-14aa914da95d_3422x1218.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><pre><code><code># Force HTTP/2
curl -I --http2 https://example.com

# Attempt HTTP/3 (curl must be built with nghttp3/quiche)
curl -I --http3 https://example.com

# Detailed HTTP/2 framing
nghttp -ans https://example.com

# QUIC packet-level trace (advanced)
sudo qlogctl &#8230; (platform-specific) </code></code></pre><div><hr></div><h2>Minimal Nginx Config Examples</h2><p>HTTP/2 Enablement (production-stable):</p><pre><code>server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate     /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/privkey.pem;

    location / {
        root /var/www/html;
        index index.html;
    }
}</code></pre><p>HTTP/3 (QUIC) Example (requires nginx-quic or alternative like Caddy):</p><pre><code>server {
    listen 443 ssl http2;
    listen 443 quic reuseport;

    server_name example.com;

    ssl_certificate     /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/privkey.pem;

    add_header Alt-Svc &#8216;h3=&#8221;:443&#8221;; ma=86400&#8217;;

    location / {
        root /var/www/html;
        index index.html;
    }
}</code></pre><p>Note: Mainline Nginx may not yet include native QUIC in all distributions&#8212;verify your build.</p><div><hr></div><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/6tYQq/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7498d84-9e74-417a-8e51-cfea04a8d7e3_1220x1172.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a0c1183-b8a4-44fa-904d-0bf975e88f62_1220x1242.png&quot;,&quot;height&quot;:483,&quot;title&quot;:&quot;Quick Reference Cheat-Sheet&quot;,&quot;description&quot;:&quot;Create interactive, responsive &amp; beautiful charts &#8212; no code required.&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/6tYQq/1/" width="730" height="483" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/rvrIt/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3fab5343-1af1-4c04-b46e-5c5a96417204_1220x768.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a704fc35-2b48-44f9-9533-fbe3715efbd3_1220x838.png&quot;,&quot;height&quot;:409,&quot;title&quot;:&quot;Reference Index&quot;,&quot;description&quot;:&quot;Create interactive, responsive &amp; beautiful charts &#8212; no code required.&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/rvrIt/1/" width="730" height="409" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><div><hr></div><h2>Closing Thought</h2><p>Every upgrade of HTTP rewired how the web feels.<br>HTTP/2 gave us speed through multiplexing.<br>HTTP/3 gave us resilience through QUIC.<br>TLS 1.3 and Zero-Trust made every hop secure by design.</p><blockquote><p>We don&#8217;t code the protocol &#8212;<br>But it decides how fast, safe, and seamless our code feels to the world.</p><p>If you want to learn above detail, as part of mentoring conversation reach back to us at <a href="https://prabodh.in">prabodh</a></p></blockquote>]]></content:encoded></item><item><title><![CDATA[Understanding RSA Cryptography]]></title><description><![CDATA[A Mathematical Journey]]></description><link>https://blog.prabodh.in/p/understanding-rsa-cryptography</link><guid isPermaLink="false">https://blog.prabodh.in/p/understanding-rsa-cryptography</guid><dc:creator><![CDATA[Vikas Putcha]]></dc:creator><pubDate>Fri, 05 Sep 2025 03:30:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0yF2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Bridging Pure Mathematics and Computer Science</strong></p><p><em>Want to understand the mathematical foundations of one of the most important cryptographic systems in the digital world? read through this article &#8230;</em></p><p><strong>Introduction</strong></p><p>This article explores RSA cryptography from a mathematical perspective, designed to bridge the gap between pure mathematics and its real-world applications in computer science. Through clear explanations and practical examples, we'll discover how elegant</p><p>mathematical concepts like prime numbers, modular arithmetic, and Fermat's Little Theorem come together to create one of the most important encryption systems in the digital world.</p><p>RSA was developed by <strong>Ron Rivest, Adi Shamir, and Leonard Adleman</strong> at the Massachusetts Institute of Technology (MIT) in 1977. This asymmetric cryptosystem revolutionized secure communication by using the mathematical difficulty of factoring large composite numbers as its foundation.</p><p><strong>Foundation Concepts: Prime Numbers and Coprimality</strong></p><p>Before diving into RSA, let's establish the fundamental mathematical building blocks.</p><p><strong>Prime Numbers</strong></p><p>A <strong>prime number</strong> is a natural number greater than 1 that has exactly two distinct positive divisors: 1 and itself.</p><pre><code><strong>Examples:

1. </strong>5 is prime because its only factors are 1 and 5

<strong>2.</strong> 17 is prime because it cannot be divided evenly by any number except 1 and 17<strong>

Note: </strong>The number 1 is not considered prime because it has only one factor (itself).</code></pre><p><strong>Coprime Numbers</strong></p><p>Two integers a and b are <strong>coprime</strong> (or relatively prime) if their greatest common divisor equals 1:</p><pre><code>gcd(a, b) = 1</code></pre><p>This means they share no common positive factors other than 1.</p><pre><code><strong>Examples:

1.</strong> (8, 15) are coprime because:
     Factors of 8:  {1, 2, 4, 8}
     Factors of 15: {1, 3, 5, 15}
     Common factors: {1} only

<strong>2.</strong> (8, 12) are NOT coprime because they share factors 2 and 4 besides 1</code></pre><p><strong>Division and Modular Arithmetic</strong></p><p><strong>Understanding Division with Remainders</strong></p><p>When we divide one integer by another, we can express the relationship using the <strong>division algorithm</strong>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;B= q &#215; A + r&quot;,&quot;id&quot;:&quot;IJOHMKRUQV&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where:</p><ul><li><p>B is the dividend (number being divided)</p></li><li><p>A is the divisor</p></li><li><p>q is the quotient (how many times A goes into B)</p></li><li><p>r is the remainder (what's left over)</p></li></ul><p><strong>Important constraint:</strong> 0 &#8804; r &lt; A (the remainder is always less than the divisor)</p><pre><code><strong>Examples:

1. </strong>A = 4, B= 12 : We get 12 = 3 &#215; 4 + 0, so q= 3, r = 0
<strong>2.</strong> A = 4, B= 13 : We get 13 = 3 &#215; 4 + 1, so q= 3, r = 1</code></pre><p><strong>Modular Arithmetic</strong></p><p><strong>Modular arithmetic</strong> is the mathematics of remainders. When we divide B by A, we write: <strong>B mod A = r</strong></p><p>By the division algorithm, there exist integers q and r such that:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;B = q \\times A + r \\quad \\text{with} \\quad 0 \\leq r < |A|&quot;,&quot;id&quot;:&quot;LJVDHAMOBH&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><p><strong>Key Properties:</strong></p><ul><li><p>The remainder &#8216;<strong>r</strong>&#8217; is unique when  0 &#8804; r &lt; |A|</p></li><li><p>We use the notation B &#8801; C (mod A) meaning B and C are congruent modulo A</p></li><li><p>This means B and C leave the same remainder when divided by A</p></li><li><p>Congruence modulo A is an equivalence relation (reflexive, symmetric, transitive)</p></li></ul><p><strong>The Circular Nature of Modular Arithmetic</strong></p><p>Modular arithmetic behaves like circular (clock) arithmetic: residues 0 to A&#8722; 1 sit on a cycle and operations wrap around when they reach A.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0yF2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0yF2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 424w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 848w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 1272w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0yF2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png" width="714" height="680" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:680,&quot;width&quot;:714,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:57442,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/172571544?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0yF2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 424w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 848w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 1272w, https://substackcdn.com/image/fetch/$s_!0yF2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca6a2a26-7ca9-4eeb-acee-d69d7eccac59_714x680.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em>Figure 1: Modular arithmetic cycle for x mod 4, showing how numbers with the same remainder are grouped together</em></p><p>For example, if we consider x mod 4 where x &gt; 0, we see a natural cycle:</p><ul><li><p>1 mod 4 = 1, 5 mod 4 = 1, 9 mod 4 = 1, 13 mod 4 = 1</p></li><li><p>2 mod 4 = 2, 6 mod 4 = 2, 10 mod 4 = 2, 14 mod 4 = 2</p></li><li><p>3 mod 4 = 3, 7 mod 4 = 3, 11 mod 4 = 3, 15 mod 4 = 3</p></li><li><p>4 mod 4 = 0, 8 mod 4 = 0, 12 mod 4 = 0, 16 mod 4 = 0</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uTxo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uTxo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 424w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 848w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 1272w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uTxo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png" width="288" height="279" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:279,&quot;width&quot;:288,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:46197,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/172571544?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uTxo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 424w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 848w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 1272w, https://substackcdn.com/image/fetch/$s_!uTxo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33be913d-6bf5-4ccf-9ccf-6f7637d84eab_288x279.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em>Figure 2: Concentric circle representation showing how 8 mod 4 = 0, demonstrating the cyclical nature of modular arithmetic</em></p><p>These visual representations help us understand that modular arithmetic creates natural groupings or "equivalence classes" of numbers that share the same remainder.</p><p><strong>Cryptography Fundamentals</strong></p><p><strong>Cryptography</strong> is the science of protecting information by transforming it so that only authorized parties can access it.</p><p><strong>Key Terms:</strong></p><ul><li><p><strong>Plaintext:</strong> The original, readable message</p></li><li><p><strong>Ciphertext:</strong> The encrypted, protected message</p></li><li><p><strong>Encryption:</strong> The process of converting plaintext to ciphertext</p></li><li><p><strong>Decryption:</strong> The process of recovering plaintext from ciphertext</p></li></ul><p><strong>Building Up to RSA: Simple Cipher Examples</strong></p><p><strong>Additive Cipher (Caesar Cipher)</strong></p><p>The Caesar cipher shifts each letter by a fixed number of positions in the alphabet using modular arithmetic.</p><pre><code><strong>Encryption Formula:

</strong>C = (P &#8722; 65 + k) mod 26 + 65</code></pre><p><code>Where: </code></p><ul><li><p>P = ASCII value of plaintext letter</p></li><li><p>C = ASCII value of ciphertext letter</p></li><li><p>k = shift key (0&#8722; 25)</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5aT4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5aT4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 424w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 848w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 1272w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5aT4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png" width="1456" height="265" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:265,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55182,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/172571544?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5aT4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 424w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 848w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 1272w, https://substackcdn.com/image/fetch/$s_!5aT4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa57b5b1f-f205-4bbd-abb5-bcacf4c8c1fd_1888x344.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Decryption Using Additive Inverse</strong></p><p>To decrypt, we need the <strong>additive inverse</strong> of the key k in mod 26  arithmetic.</p><p>By definition, the additive inverse of k is the number -k such that:</p><pre><code>k + (-k) &#8801; 0 (mod 26)</code></pre><p>Practically, this means:</p><pre><code>additive inverse of k mod 26 = (&#8722;k) mod 26

General formal for finding additive inverse of k mod n is
(&#8722;k) mod n = ( n &#8722; (k mod n) ) mod n;

(-k) mod 26 = (26 - (17 mod 26 ) mod 26;
(-k) mod 26 = (26 - 17) mod 26 = 9 mod 26;

&#8756; additive inverse of <strong>17 mod 26</strong> is <strong>9 mod 26</strong></code></pre><pre><code><strong>Decryption Formula:
</strong>P = ( (C - 65) + 9 ) mod 26 + 65; 

getting the plain text from above cipher values is left as an exercise to the reader.</code></pre><p><strong>The Concept of Modular Inverses</strong></p><p>The "walk forward until you return home" principle applies to different types of operations:</p><p><strong>Multiplicative Inverse</strong></p><p>The <strong>multiplicative inverse</strong> of modulo n is a number a<sup>-1</sup> such that:</p><pre><code>a &#215; a<sup>&#8722;1</sup> &#8801; 1 (mod n)</code></pre><p><strong>Example:</strong> In mod 7 , we have 3 &#215; 5 = 15 &#8801; 1 (mod 7), so 5 is the multiplicative inverse of 3.</p><p><strong>Exponential Inverse</strong></p><p>In RSA, we use the fact that raising to some power <strong>e</strong> can be "undone" by raising to another power <strong>d</strong>, provided:</p><pre><code>e &#215; d &#8801; 1 (mod &#966;(n))</code></pre><p><strong>Fermat's Little Theorem: The Foundation for RSA</strong></p><p><strong>Fermat's Little Theorem</strong> states that if <strong>p</strong> is prime and <strong>a</strong> is not divisible by p, then:</p><p>a<sup>p&#8722;1</sup> &#8801; 1 (mod p)</p><p><strong>Euler's Theorem</strong> (generalization): If gcd(a, n) = 1, then:</p><pre><code>a&#966;(n) &#8801; 1 (mod n)</code></pre><p>Where <strong>&#966;(n)</strong> is <strong>Euler's totient function</strong>, counting how many numbers <strong>&#8804; n</strong> are coprime to <strong>n</strong>.</p><p><strong>Key Formulas:</strong></p><ul><li><p><strong>For prime </strong><em><strong>p</strong></em>:  <em>&#966;(p) = p&#8722; 1</em></p></li><li><p><strong>For product of two primes: </strong><em>&#966;(pq) = (p&#8722; 1)(q&#8722; 1)</em></p></li><li><p>The <strong>generalised formula</strong> for the total of <strong>Euler&#8217;s totient function</strong>  for any positive integer is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;{\\varphi(n) = n \\prod_{i=1}^{k} \\left(1 - \\frac{1}{p_i}\\right)}\n\n&quot;,&quot;id&quot;:&quot;XGDRPISUFA&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where p1, p2, &#8230;,pk are the distinct prime factors of </p></li></ul><p><strong>Example:</strong> For n = 10 = 2 &#215; 5 :</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\varphi(10) = 10 \\times \\left(1 - \\tfrac{1}{2}\\right) \\times \\left(1 - \\tfrac{1}{5}\\right) \n= 10 \\times \\tfrac{1}{2} \\times \\tfrac{4}{5} = 4\n&quot;,&quot;id&quot;:&quot;KTHQCEAHRS&quot;}" data-component-name="LatexBlockToDOM"></div><p>The numbers 1, 3, 7, 9 are exactly the four integers between 1 and 10 that are coprime to 10.</p><p><strong>RSA Cryptosystem: A Complete Walkthrough</strong></p><p>Now let's see how all these mathematical concepts come together in RSA:</p><p>The security of RSA relies on the difficulty of factoring <strong>n</strong> back into its prime components <strong>p</strong> and <strong>q</strong>.</p><p><strong>Why This Matters:</strong> &#966;(n) counts how many numbers from <strong>1 to n</strong> are coprime with <strong>n</strong>. This creates the mathematical space where our encryption/decryption exponents will operate.</p><pre><code>RSA String Encryption Demo, Pick two distinct primes from this set:
11 13 17 19 23 29 31 37 41 43 47 53

Step-by-Step RSA Implementation, Let's work through RSA using p = 13 and  q = 17:

Step 1: Build modulus n = p &#215; q;  n = p &#215; q = 13 &#215; 17 = 221
Step 2: Euler's Totient &#966;(n) = (p-1)(q-1)
        &#966;(n) = (13-1)(17-1) = 12 &#215; 16 = 192
Step 3: Choose public exponent e with gcd(e, &#966;(n)) = 1
        Count of valid public exponents e in [2, &#966;(n)-1]:  
        &#966;(n)=(p&#8722;1)(q&#8722;1)=12&#8901;16=192; 
        &#966;( &#966;(n) ) = &#966;(192) = 64; 
        Some valid e values: 5 7 11 13 17 19 23 25 29 31 35 37

        Selected: e = 5
Step 4: Compute private exponent d = e&#8315;&#185; (mod &#966;(n))
        d is the modular inverse of e modulo &#966;(n)

        e &#215; d &#8801; 1 (mod &#966;(n)) &#8594; 5 &#215; 77 &#8801; 1 (mod 192)
        Therefore: d = 77

Public Key  : (e = 5, n = 221)
Private Key : (d = 77, n = 221)</code></pre><p><strong>Encryption and Decryption Demo</strong></p><p>Now let's encrypt the message "HELLO":</p><p>Demo: Encrypt/Decrypt a string message</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WhOc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WhOc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 424w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 848w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 1272w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WhOc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png" width="1456" height="288" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:288,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:47976,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/172571544?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WhOc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 424w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 848w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 1272w, https://substackcdn.com/image/fetch/$s_!WhOc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4094963c-d54e-49b5-935a-07cf275f28a1_1885x373.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Mathematical Verification</strong></p><p><strong>Encryption Formula:</strong></p><p>C = P<sup>e</sup> mod n = P<sup>5</sup> mod 221</p><ul><li><p>H (72): 72<sup>5</sup> mod 221 = 89 &#10003;</p></li><li><p>E (69): 69<sup>5</sup> mod 221 = 205&#10003;</p></li><li><p>L (76): 76<sup>5</sup> mod 221 = 111&#10003;</p></li><li><p>O (79): 79<sup>5</sup> mod 221 = 27 &#10003;</p></li></ul><p><strong>Decryption Formula:</strong></p><p>P= C<sup>d</sup> mod n = C<sup>77</sup> mod 221</p><ul><li><p>89<sup>77</sup> mod 221 = 72 (H)  &#10003;</p></li><li><p>205<sup>77</sup> mod 221 = 69 (E) &#10003;</p></li><li><p>111<sup>77</sup> mod 221 = 76 (L) &#10003;</p></li><li><p>27<sup>77</sup> mod 221 = 79 (O)  &#10003;</p></li></ul><p><strong>Why RSA Decryption Works</strong></p><p>The mathematical elegance of RSA lies in Euler's theorem. Since we choose e and d such that:</p><pre><code>e &#215; d &#8801; 1 (mod &#966;(n))</code></pre><p>This means e &#215; d= 1 + k &#215; &#966;(n) for some integer k.</p><p>Therefore: (P<sup>e</sup>)<sup>d</sup> = P<sup>ed</sup> = P<sup>1+k&#966;(n)</sup> = P &#215; (P<sup>&#966;(n)</sup>)k</p><p>By Euler's theorem, if gcd(P , n) = 1, then P &#966;(n) &#8801; 1 (mod n).</p><p>Thus:</p><pre><code>P &#215; (1)<sup>k</sup> &#8801; P (mod n)</code></pre><p>This guarantees that encryption followed by decryption recovers the original message.</p><p><strong>Additional Mathematical Insights</strong></p><pre><code>&#966;(n) = 192 factors into: 2&#8310; &#215; 3&#185;
&#966;(&#966;(n)) = &#966;(192) = 64 = 192 &#215; &#8719;(1 - 1/p) over its prime factors p</code></pre><p>The factorization reveals that there are 64 valid choices for the public exponent <strong>e.</strong></p><p><strong>RSA Security, The Hard Problem</strong></p><p>RSA's security relies on the <strong>integer factorization problem</strong>: given a large composite number <strong>n = p &#215; q</strong> , it is computationally infeasible to find <strong>p and q</strong> when they are large primes (typically hundreds of digits long).</p><p><strong>Why this matters:</strong></p><ul><li><p>Anyone can see the public key (n, e)</p></li><li><p>To decrypt without the private key <strong>d</strong>, one would need to factor <strong>n</strong> to find <strong>p</strong> and <strong>q</strong></p></li><li><p>With <strong>p</strong> and <strong>q</strong>, one could compute &#966;(n) and then find <strong>d</strong></p></li><li><p>Current factoring algorithms cannot handle sufficiently large <strong>n</strong> in reasonable time</p></li></ul><p><strong>From Toy Example to Real World</strong></p><p>In this demonstration, n = 221 can be factored easily. But with real RSA:</p><ul><li><p>Key sizes are typically 2048 bits or larger</p></li><li><p>Prime numbers <strong>p </strong>and <strong>q</strong> are hundreds of digits long</p></li><li><p>Factoring such large <strong>n </strong>is computationally infeasible with current technology</p></li></ul><p>RSA&#8217;s effective security is much less than its key size for example, 1024 &#8776; 80 bits, 2048 bits RSA &#8776; 112 bits, 3072 bits RSA &#8776; 128 bits, and so on. Due to the mathematical structure and patterns within RSA keys, as well as the efficiency of integer factorization algorithms.  we shall discuss on that in another article, that also covers Attack Algorithms, Symmetric Ciphers like AES and more.</p><p><strong>Conclusion</strong></p><p>RSA cryptography demonstrates the beautiful intersection of pure mathematics and practical computer science. Starting from elementary concepts like prime numbers and modular arithmetic, we've built up to understanding one of the most important cryptographic systems in use today.</p><p><strong>Key insights:</strong></p><ul><li><p><strong>Mathematical Foundation:</strong> Prime numbers and modular arithmetic provide the building blocks</p></li><li><p><strong>Elegant Design:</strong> Fermat's Little Theorem and Euler's theorem enable the encryption/decryption process</p></li><li><p><strong>Practical Security:</strong> The difficulty of factoring large numbers protects real-world communications</p></li><li><p><strong>Asymmetric Nature:</strong> Public and private keys enable secure communication without prior key sharing</p></li></ul><p>This mathematical exploration illustrates how abstract mathematical concepts can have profound practical applications, protecting everything from online banking to private messaging in our digital world. The elegant interplay between number theory and</p><p>cryptographic security continues to be one of the most beautiful examples of applied mathematics in computer science.</p><p>If you want to understand more about practical applications using openssl or libsodium you can reach out to us at <a href="https://prabodh.in">Prabodh</a>.</p><p><strong>References and Further Reading</strong></p><p><em><a href="https://www.cs.umd.edu/~jkatz/imc.html">Introduction to Modern Cryptography</a></em><a href="https://www.cs.umd.edu/~jkatz/imc.html"> by Katz and Lindell</a></p><p><em><a href="https://agorism.dev/book/crypto/%5BGraduate%20texts%20in%20mathematics%20%20114%5D%20Neal%20Koblitz%20-%20Course%20In%20Number%20Theory%20And%20Cryptography%20(1994,%20Springer).pdf">A Course in Number Theory and Cryptography</a></em><a href="https://agorism.dev/book/crypto/%5BGraduate%20texts%20in%20mathematics%20%20114%5D%20Neal%20Koblitz%20-%20Course%20In%20Number%20Theory%20And%20Cryptography%20(1994,%20Springer).pdf"> by Neal Koblitz</a></p><p><a href="https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/what-is-modular-arithmetic">Khan Academy's course on modular arithmetic</a></p><p><a href="https://en.wikipedia.org/wiki/RSA_cryptosystem">The original RSA paper: "A Method for Obtaining Digital Signatures and Public-Key Cryptosystems" (1978)</a></p>]]></content:encoded></item><item><title><![CDATA[Unlocking Better Communication]]></title><description><![CDATA[A Deep Dive into Yoodli&#8217;s AI Features]]></description><link>https://blog.prabodh.in/p/unlocking-better-communication</link><guid isPermaLink="false">https://blog.prabodh.in/p/unlocking-better-communication</guid><dc:creator><![CDATA[Vikas Putcha]]></dc:creator><pubDate>Tue, 26 Aug 2025 03:30:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2tk6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We&#8217;ve all felt nervous before a presentation, interview, or tough conversation. Imagine having a coach who gives you real-time tips&#8212;without the pressure or the risk of missing your moment. That&#8217;s Yoodli, your AI-powered, judgment-free speech coach.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2tk6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2tk6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2tk6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:142432,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.prabodh.in/i/171826596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2tk6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!2tk6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8195500-df6b-4f6c-b163-b6706fc35882_1024x1024.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>What Is Yoodli?</h2><p>At its core, Yoodli is a personal AI speech coach that delivers <strong>private, real-time feedback</strong> on your communication. Whether you&#8217;re preparing for a keynote, a sales pitch, or a tough feedback session, it gives you the kind of insights usually reserved for professional coaches&#8212;only here, it&#8217;s always available and tailored to you.</p><h2>Yoodli's Core Modes of Practice</h2><p>Yoodli offers multiple ways to practice and grow, depending on your needs:</p><ul><li><p><strong>Pitch/Presentation Mode</strong> &#8211; Record your talk, review detailed feedback, and even practice with AI-generated follow-up questions.</p></li><li><p><strong>Interview Mode</strong> &#8211; Choose a job role, set your interviewer&#8217;s demeanor, and experience dynamic Q&amp;A practice.</p></li><li><p><strong>Roleplay Mode</strong> &#8211; Rehearse crucial conversations&#8212;like asking for a raise or handling conflict&#8212;with AI stepping into the other role.</p></li><li><p><strong>Video Call Coaching</strong> &#8211; Yoodli can join live Zoom, Teams, or Google Meet calls, offering subtle nudges such as &#8220;slow down&#8221; or &#8220;avoid filler words.&#8221; While it takes some getting used to during deep discussions, it can dramatically improve live performance.</p></li><li><p><strong>Desktop App Feedback</strong> &#8211; On Windows or macOS, record conversations and receive instant, private coaching.</p></li></ul><div><hr></div><h2>What Makes Yoodli Stand Out?</h2><h3>Real-Time, Judgment-Free Feedback</h3><p>Think of Yoodli as a <strong>smart mirror for communication</strong>. It transcribes your speech and provides instant analytics on filler words, pacing, clarity, and tone&#8212;without criticism, just data-driven guidance.</p><h3>Focused on Both Content and Delivery</h3><p>Most tools flag tone or speed, but Yoodli goes further&#8212;helping you refine <em>what</em> you say and <em>how</em> you say it. From rephrasing unclear ideas to sharpening delivery, it covers the full spectrum of effective communication.</p><h3>Realistic Roleplay Scenarios</h3><p>Instead of rehearsing alone, you engage with an AI that reacts, questions, and even challenges you&#8212;simulating real dialogue in a risk-free environment.</p><h3>Personalized Progress Tracking</h3><p>Over time, Yoodli tracks your growth: filler word reduction, pacing improvements, clarity gains, and confidence trends. You don&#8217;t just feel progress&#8212;you see it.</p><div><hr></div><h2>Sample Scenarios Where Yoodli Shines</h2><ul><li><p><strong>Public Speaking</strong>: Record a TED-style talk and refine both substance and style.</p></li><li><p><strong>Crucial Conversations</strong>: Practice negotiating a raise, addressing conflict, or giving feedback in a safe environment.</p></li><li><p><strong>Sales &amp; Business</strong>: Sharpen your pitch and delivery before you walk into the real deal.</p></li></ul><div><hr></div><h2>&#10024; Takeaway</h2><p>We&#8217;re entering an era where AI isn&#8217;t just crunching numbers&#8212;it&#8217;s helping us become <strong>better humans in conversation</strong>. With the right feedback loop, practice isn&#8217;t just for musicians or athletes. You can practice your words, your tone, your confidence&#8212;and show up as the best version of yourself.</p><p>At <strong><a href="https://prabodh.in">Prabodh</a></strong>, we don&#8217;t just design engaging workshops&#8212;we strive to make you more successful by discovering and sharing the tools that give you an edge.</p><p>&#128073; Curious to see how Yoodli works? Try it out <a href="https://yoodli.ai">here</a> and start transforming the way you communicate.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.prabodh.in/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Beyond React Hooks]]></title><description><![CDATA[How Signals Complement React Hooks]]></description><link>https://blog.prabodh.in/p/beyond-react-hooks</link><guid isPermaLink="false">https://blog.prabodh.in/p/beyond-react-hooks</guid><dc:creator><![CDATA[Vikas Putcha]]></dc:creator><pubDate>Tue, 19 Aug 2025 04:30:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!i4EK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i4EK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i4EK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i4EK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:56090,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://vikasputcha.substack.com/i/171288845?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i4EK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!i4EK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ae95002-c1df-4499-a169-ceb0ac01f5f3_1536x1024.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>When React introduced Hooks in 2019, it changed the way we thought about building components. Suddenly, we could manage state and side effects in functional components without juggling class lifecycle methods. Hooks like <code>useState</code> and <code>useEffect</code> became the bread and butter of modern React development.</p><p>But as applications grow, developers are bumping into the <em>limits of Hooks</em>: unnecessary re-renders, complicated dependency arrays, and performance bottlenecks in fine-grained updates.</p><p>This is where <strong>Signals</strong> come in. Signals don&#8217;t replace Hooks&#8212;they <strong>complement them</strong>&#8212;and offer a fresh approach to reactivity that&#8217;s already gaining traction in frameworks like SolidJS, Angular, and even experiments in React&#8217;s ecosystem.</p><h2>A Quick Recap: React Hooks</h2><p>Here&#8217;s the classic way we handle state with Hooks:</p><pre><code><code>import { useState } from "react";

function Counter() {

  const [count, setCount] = useState(0);

  return (
    &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
      Count is {count}
    &lt;/button&gt;
  );
}</code></code></pre><p></p><p>This works beautifully. But if this <code>count</code> state was passed deep into multiple child components, React would need to re-render <em>all of them</em> whenever <code>count</code> changes&#8212;even if they don&#8217;t directly use it.</p><h2>What Are Signals?</h2><p>A <strong>Signal</strong> is a special kind of state container.<br>Think of it like a box that holds a value, and whenever the value changes, <em>only the places that use it update</em>&#8212;no unnecessary re-renders.</p><p>Here&#8217;s the same counter implemented with Signals (example using <a href="https://www.npmjs.com/package/@preact/signals-react">@preact/signals-react</a>):</p><pre><code><code>import { signal } from "@preact/signals-react";

const count = signal(0);
function Counter() {

  return (
    &lt;button onClick={() =&gt; count.value++}&gt;
      Count is {count.value}
    &lt;/button&gt;
  );
}</code></code></pre><p>Notice a few things:</p><ul><li><p>No <code>useState</code>.</p></li><li><p>No re-rendering the entire component tree.</p></li><li><p>Only the parts of the UI that directly read <code>count.value</code> update.</p></li></ul><h2>Why Signals Complement Hooks</h2><p>Instead of replacing Hooks, Signals solve some of their shortcomings:</p><h3>1. <strong>Fine-grained reactivity</strong></h3><ul><li><p>Hooks: Changing state re-renders the whole component.</p></li><li><p>Signals: Only the elements that <em>read</em> the signal update.</p></li></ul><h3>2. <strong>No dependency arrays</strong></h3><ul><li><p>With <code>useEffect</code>, we manually track dependencies:</p></li></ul><pre><code><code>useEffect(() =&gt; {
  fetchData(query);
}, [query]);</code></code></pre><ul><li><p>With Signals, the system knows what depends on what, so no arrays are needed.</p></li></ul><h3>3. <strong>Global state without Context</strong></h3><ul><li><p>Instead of setting up a React Context and a provider, a signal can be imported and shared anywhere:</p></li></ul><p><code>export const user = signal(null);</code></p><p>Any component reading <code>user.value</code> will automatically update when it changes.</p><h3><strong>Signals + Hooks in Practice</strong></h3><p>The sweet spot is <strong>using both together</strong>.</p><p>For example, keep Hooks for local component state, and Signals for global/shared reactive data:</p><pre><code><code>import { signal } from "@preact/signals-react";
import { useState } from "react";

const theme = signal("light");
function Toolbar() {
  const [open, setOpen] = useState(false);

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setOpen(!open)}&gt;Menu&lt;/button&gt;
      &lt;button onClick={() =&gt; theme.value = theme.value === "light" ? "dark" : "light"}&gt;
        Toggle Theme
      &lt;/button&gt;

      &lt;p&gt;Theme is: {theme.value}&lt;/p&gt;
    &lt;/div&gt;

  );

}</code></code></pre><ul><li><p><code>open</code> (local UI toggle) works great with <code>useState</code>.</p></li><li><p><code>theme</code> (shared across the app) is better suited for a Signal.</p></li></ul><h2>The Road Ahead</h2><p>React&#8217;s own team is experimenting with concepts like <strong>React Forget</strong> (a compiler that could make Hooks behave more like Signals under the hood). Meanwhile, libraries like <code>@preact/signals-react</code> are giving us a glimpse of the future.</p><p>If Hooks gave us a declarative way to manage state, Signals give us a <strong>more efficient and predictable reactivity model</strong>. Together, they create a developer experience that&#8217;s both powerful and ergonomic.</p><div><hr></div><h2>&#10024; Closing Thoughts</h2><p>Hooks aren&#8217;t going anywhere. They&#8217;re still the foundation of React apps. But Signals add a new layer:</p><ul><li><p>Fewer re-renders</p></li><li><p>Cleaner reactive code</p></li><li><p>A simpler way to manage shared state</p></li></ul><p>Think of Hooks as the <strong>engine</strong>, and Signals as a <strong>turbocharger</strong>.</p><p>The next time you find yourself struggling with complex <code>useEffect</code> dependencies or heavy global state management, give Signals a try&#8212;you may find they make your React codebase feel <em>lighter</em> and <em>faster</em>.</p>]]></content:encoded></item></channel></rss>