<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrei Novikov</title>
    <description>The latest articles on DEV Community by Andrei Novikov (@anovisoft).</description>
    <link>https://dev.to/anovisoft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4114836%2F069bbad7-0b50-44eb-a7bf-5e4a554cda72.jpg</url>
      <title>DEV Community: Andrei Novikov</title>
      <link>https://dev.to/anovisoft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anovisoft"/>
    <language>en</language>
    <item>
      <title>Rendering live broadcast graphics without a GPU, and what four hours actually cost</title>
      <dc:creator>Andrei Novikov</dc:creator>
      <pubDate>Sat, 12 Sep 2026 11:51:04 +0000</pubDate>
      <link>https://dev.to/anovisoft/rendering-live-broadcast-graphics-without-a-gpu-and-what-four-hours-actually-cost-3c9l</link>
      <guid>https://dev.to/anovisoft/rendering-live-broadcast-graphics-without-a-gpu-and-what-four-hours-actually-cost-3c9l</guid>
      <description>&lt;p&gt;Short recap, because this is the second half of a story. &lt;a href="https://dev.to/anovisoft/how-our-broadcast-graphics-left-vmix-one-bottleneck-at-a-time-1o81"&gt;In the previous article&lt;/a&gt; I described how our on-air graphics at VSporte left vMix. The overlay became a web page fed into the mixer as a single input, which took the graphics out of vMix's memory and made them testable. Then Rive moved the layout work off developers and onto designers. That last step had a consequence nobody planned: a graphic was now a file with a state machine, driven by plain data. It did not need a browser to render. And it had never needed a GPU, we had just always rendered it through tools that came with one attached.&lt;/p&gt;

&lt;p&gt;Everything below is VSporte engineering too: real feeds, measured numbers, and a container that does what I say it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can the rendering leave the building?
&lt;/h2&gt;

&lt;p&gt;Once the graphic is a Rive file plus a JSON state, the renderer can be anything that runs the Rive state machine and rasterizes vectors.&lt;/p&gt;

&lt;p&gt;Rive is something you normally render on the web, in a browser or an app, and that is where we ran it. I wanted to know whether the same file could be rendered headless, on a server with no GPU in it at all, and what a live broadcast would cost if it could. Which is the obvious question restated: why is there still a GPU workstation in a rented room attached to every parallel broadcast?&lt;/p&gt;

&lt;p&gt;The path was not a straight line. First browser screenshots driven by a headless browser, then a WebAssembly renderer on CPU, then a native build, each cheaper and more stable than the last. Before committing to the native build I benchmarked it to establish that thirty frames a second at 1080p is reachable on eight cores, and catalogued what the native path gives up, fonts and automatic layout. That is the sort of thing that decides an engine choice more often than raw throughput does.&lt;/p&gt;

&lt;p&gt;What I ended up with is a single container. Input is an SRT stream, output is an SRT stream with the graphics burned in. Inside it are four threads. &lt;strong&gt;StateManager&lt;/strong&gt; holds a websocket subscription to the graphics state, with an HTTPS polling fallback for when the socket will not establish, and the state itself is plain JSON naming the scene file, the state machine, and the view model as key value pairs, and downloads the Rive file and its assets. &lt;strong&gt;SrtReceiver&lt;/strong&gt; decodes incoming video into raw frames. &lt;strong&gt;RiveRenderer&lt;/strong&gt; runs the state machine and rasterizes into an RGBA buffer through Skia on CPU. &lt;strong&gt;Compositor&lt;/strong&gt; blends the overlay over the frame with premultiplied alpha, encodes with libx264, and pushes the result back out over SRT. The whole thing is a Docker image whose most important environment variable is the URL it reads its graphics state from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fczvco7eyl6e3tsitpwfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fczvco7eyl6e3tsitpwfa.png" alt=" " width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skia is the part doing the real work in that third thread and it deserves the credit by name. It is a mature 2D rasterizer, the same engine that draws Chrome's canvas and Android's UI, and vector artwork with a bounded number of shapes is what it is built for. Rive supplies the scene and the state machine, Skia turns it into pixels. Worth saying why Skia and not Rive's own renderer, which is where Rive itself has moved: that renderer is designed around the GPU, and the Skia backend was the mature path to a raster surface on CPU. That pairing is the reason 1080p at thirty frames a second sits comfortably on eight cores. Worth knowing before you copy the choice: Rive has retired that backend on iOS, Android and WASM. It is still there on Linux, which is where this container lives, but it is a dependency with a direction of travel, and that belongs on the risk list rather than in a footnote.&lt;/p&gt;

&lt;p&gt;It works on CPU because of what broadcast graphics actually are: vector shapes, text and simple transitions at 1080p. The GPU was never required by the pixels. It was required by the tools that used to draw them.&lt;/p&gt;

&lt;p&gt;One thing about the topology is worth stating explicitly, because it is the first question anyone from a broadcaster asks and the cloud pitch never answers it. In the topology I built, the clean feed does not go through the container. It runs past it, untouched, straight to the mixer, and what the container receives and burns into is the dirty path. Two consequences fall out of that. The clean feed still exists, which matters to every international partner, regional version and ad insertion downstream, and none of them were ever going to accept a workflow that had only one copy of the program feed with graphics welded into it. And the failure story is smaller than it looks from outside: the container sits inline in one path, the one carrying graphics. If it dies, the mixer still has clean video arriving, and you cut to it. That is a few seconds of a plainer looking broadcast, not a dead one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The latency budget, which is where the real work was
&lt;/h2&gt;

&lt;p&gt;Anything live has a budget, and the useful question is not "is it low latency" but "where do the milliseconds sit". Ours:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SRT input latency.&lt;/strong&gt; The buffer that lets SRT recover lost packets, a couple hundred milliseconds in practice. The single largest line item, and a deliberate purchase. Push it down and you trade robustness for delay, and on a real network you feel that trade immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting state to the renderer.&lt;/strong&gt; State arrives over a websocket, pushed the moment it changes, so this line of the budget is close to free. There is an HTTPS polling fallback for when the socket will not establish, and which one is the default was not an aesthetic choice. The target was under a second from the data changing to the frame that shows it, and a poll interval spends a good part of that budget before the renderer has heard anything at all. Keeping both paths in the same binary is worth it anyway: a fallback you can measure against the default is how you find out what the transport is actually costing you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoder.&lt;/strong&gt; libx264 tuned for zerolatency with a fast preset. Zerolatency matters more than the preset, because it disables the frame reordering and lookahead that otherwise silently add delay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queues between the threads.&lt;/strong&gt; This one bit us. If the compositor falls behind, frames accumulate, and an accumulating queue is latency you cannot see in any config file. We settled on dropping frames deliberately when the queue grows, and logging the drop. A visible dropped frame is a much better failure than a stream drifting steadily further behind live.&lt;/p&gt;

&lt;p&gt;A subtler one on the same path: the overlay looked stuttery with nothing overloaded, because frames were arriving unevenly rather than late. Instrument decode, render and composite separately from day one. Aggregate CPU load tells you nothing about this class of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs, and how to check the number
&lt;/h2&gt;

&lt;p&gt;One container per broadcast, on a node with no GPU. The bench machine is eight dedicated vCPU and sixteen gigabytes of RAM, which is what 1080p at thirty frames a second and six megabits needs with room to spare.&lt;/p&gt;

&lt;p&gt;From there the calculation is one line: instance size, times the length of the event, times the hourly price. Two anchors so you can place your own. On the provider I ran it on, four hours land at about a dollar, disk and public address included. On AWS the equivalent box is a c7i.2xlarge, eight vCPU and sixteen gigabytes, and in a local zone it runs about forty six cents an hour on demand, so the same match is about two dollars. Pick your own region and the number moves, which is the point of having two anchors rather than one.&lt;/p&gt;

&lt;p&gt;One line item to carry across when you do: traffic. That provider bundles traffic into the machine price, so a dollar really is the whole bill. Hyperscalers charge it separately, and six megabits for four hours is roughly eleven gigabytes out, which at usual egress rates adds about another dollar on top of the two. It does not change the argument. Leaving it out of your own spreadsheet will.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr3s0hwdcnzcasauz23th.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr3s0hwdcnzcasauz23th.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am not naming the provider, because the interesting number is not mine, it is yours. Note that the two anchors differ by a factor of two and the argument survives it completely, because what this replaces is a GPU workstation, in a rented room, purchased again for every parallel show.&lt;/p&gt;

&lt;p&gt;One cost the cloud pitch usually skips, and we paid it. With vMix in the studio the finished picture is right there on the local machine. Move the render out and you have to send it back, over SRT, and on our demo rig that return leg was a machine of its own. Anyone who tells you cloud graphics is purely a subtraction has not run it.&lt;/p&gt;

&lt;p&gt;The property that matters is the shape of the curve, not the absolute number. A parallel broadcast is another container, not another machine and another room. Our demo rig ran two graphics packages over the same source feed into one receiving vMix, and going from two parallel outputs to ten is a config change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is a bad idea
&lt;/h2&gt;

&lt;p&gt;I would not pitch this as universal, because it is not.&lt;/p&gt;

&lt;p&gt;If your graphics are 3D, heavy particle work, or anything that genuinely needs shaders, the CPU rasterizer is the wrong tool and you should stop reading here. This works because broadcast graphics are mostly vectors, text and simple transitions at 1080p.&lt;/p&gt;

&lt;p&gt;If you need frame accurate integration with studio hardware, SDI in and out, genlock, tally, then a cloud container is in the wrong place on the network no matter how cheap it is.&lt;/p&gt;

&lt;p&gt;The economics also assume 1080p at thirty frames a second, and that is worth saying plainly to a European audience, because European broadcast lives at 1080i50 and 1080p50. Fifty frames is not thirty with a larger number attached to it. Push to 50p, to 4K, or to a high bitrate ladder, and the encode cost per show climbs fast enough that a cheap CPU node stops being cheap. At that point you are buying hardware again, just somewhere else. What it actually takes to hold 1080p50 on this architecture is its own article, and I would rather write that one properly than wave at it here.&lt;/p&gt;

&lt;p&gt;And if you run two marquee matches a week, the old model is fine and the migration will not pay for itself. The economics turn over when you have many low value parallel events, which is exactly the segment where a GPU station per broadcast is unbearable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part worth taking away
&lt;/h2&gt;

&lt;p&gt;The portable file made the renderer replaceable, and a replaceable renderer is what put the GPU and the rented room in question at all. None of the steps that got us there knew about the dollar. The dollar fell out at the end.&lt;/p&gt;

&lt;p&gt;So the question I would ask of your own pipeline is not "can we do this in the cloud". It is the one we kept asking: which piece of infrastructure is in there because of the work, and which is in there because of the tool that used to do the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  And where does the cloud come into it?
&lt;/h2&gt;

&lt;p&gt;Late, and by accident. Nobody set out to move broadcast graphics into a data centre. Four bottlenecks got solved in order, and by the end of them a graphic was a file, a state machine and eight cores, which is already the description of a container. That is why the dollar sits at the bottom of this article instead of the top.&lt;/p&gt;

&lt;p&gt;Two things here are articles rather than paragraphs, so I have left them out on purpose: what it takes to hold 1080p50 instead of 30, and what the graphics control platform looks like from the operator's side, which is the half of this story that is not about rendering at all. Tell me in the comments which one you would read first.&lt;/p&gt;

&lt;p&gt;I am Andrei Novikov. I spent seven years running the engineering side of VSporte and I write about backend and realtime architecture. If you are at IBC and doing something adjacent, I am interested in comparing notes.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>architecture</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>How our broadcast graphics left vMix, one bottleneck at a time</title>
      <dc:creator>Andrei Novikov</dc:creator>
      <pubDate>Tue, 08 Sep 2026 05:04:13 +0000</pubDate>
      <link>https://dev.to/anovisoft/how-our-broadcast-graphics-left-vmix-one-bottleneck-at-a-time-1o81</link>
      <guid>https://dev.to/anovisoft/how-our-broadcast-graphics-left-vmix-one-bottleneck-at-a-time-1o81</guid>
      <description>&lt;p&gt;For seven years I ran the engineering side of VSporte, a company that builds software for sports broadcasting. Everything described here is VSporte product development, done by the company's engineering teams. My part was the architecture and the calls about where the work went next.&lt;/p&gt;

&lt;p&gt;Our on-air graphics started where most production rooms start, as a folder of vMix titles files, and over a few years they left vMix completely. vMix still does the final mix. The graphics are not inside it.&lt;/p&gt;

&lt;p&gt;This is the part of the story that shipped. Three steps, and the useful thing about them is not where we ended up, it is that every fix created the next bottleneck. If you work in broadcast you will recognise at least one of them, probably the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step zero: vMix and a folder of gtzip files
&lt;/h2&gt;

&lt;p&gt;The setup we started from is the one standing in most production rooms. vMix on a workstation, and the graphics living as gtzip files, which is vMix's proprietary titles format. The operator loads the pack and configures the titles inside vMix by hand. Presets exist and they make a repeat setup cheaper than the first one, but the data behind every graphic still has to be carried through, match after match.&lt;/p&gt;

&lt;p&gt;The obvious objection is that vMix has an answer for this, and it does. &lt;a href="https://www.vmix.com/help25/DataSources.html" rel="noopener noreferrer"&gt;Data Sources&lt;/a&gt; will drive titles from Google Sheets, Excel, CSV or XML, and the standard forum advice to anyone staring at a pile of near identical graphics is exactly that: &lt;a href="https://forums.vmix.com/posts/t20042-Titles-and-GPU-memory" rel="noopener noreferrer"&gt;one title instance plus a spreadsheet&lt;/a&gt;. It is good advice and much of the industry runs on it. It also solves a narrower problem than ours. A spreadsheet collapses the variants of one graphic. A client package is not variants of one graphic, it is twenty to fifty different elements, scoreboard, lower thirds, line ups, season statistics, each its own template. The spreadsheet does not reduce that count, it does not make a template testable, and it does not change who opens the editor when a client wants one to behave differently.&lt;/p&gt;

&lt;p&gt;You can host vMix itself in the cloud, and people do. It moves the same workstation into a data center and changes nothing about how graphics are made, loaded or driven. The workflow was the problem, and the workflow stays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step one: the overlay becomes a web page
&lt;/h2&gt;

&lt;p&gt;The first real change was building our own graphics control platform and turning the on-air overlay into a web page, fed into vMix as an input layer. vMix still does the final mix. The graphics no longer live inside it.&lt;/p&gt;

&lt;p&gt;Two consequences, and if you have run vMix with a large titles pack, the first one needs no explanation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The memory load on vMix became constant.&lt;/strong&gt; A gtzip pack loads into vMix and the footprint grows with every template you add, and packs grow, because clients keep asking for one more graphic.&lt;/p&gt;

&lt;p&gt;You do not have to take my word for the ceiling, because the vendor documents it. vMix's own &lt;a href="https://help.vmix.com/graphics/2/PerformanceConsiderations.html" rel="noopener noreferrer"&gt;performance notes&lt;/a&gt; put an average HD title template at 100 to 200 MB of graphics memory and recommend no more than twenty templates open in a preset at once. A client package in our world was twenty to fifty templates. We were starting at the number where the vendor says stop.&lt;/p&gt;

&lt;p&gt;The same page carries a number that mattered more to us than the template count did. A five second full frame image sequence at 1080p60 needs nearly 2.5 GB of graphics memory, because every frame of it is a bitmap sitting in VRAM. One animated intro can therefore cost more than a dozen static templates, and animated intros are not an exotic request, they are the first thing a client asks for. The vendor's own advice is to shrink the sequence to the exact rectangle it will occupy, which works and which is also an admission of what the format costs.&lt;/p&gt;

&lt;p&gt;With the overlay as a single web input, the footprint stopped depending on the size of the package. A fixed cost instead of one that grows with every element in the pack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The graphics became testable.&lt;/strong&gt; A web page is checked with ordinary web testing practices, the same ones every frontend team already runs. In broadcast graphics that is genuinely rare. A proprietary titles format gives you no handle to test against, so graphics get verified the traditional way, by a person looking at an output and hoping the edge cases show up before air.&lt;/p&gt;

&lt;p&gt;There was a third effect on the operators. The data behind the graphics moved into the platform, structured and reusable, so nobody was configuring titles inside gtzip files anymore. Teams, scores, clocks come from the system, and the overlay binds to them.&lt;/p&gt;

&lt;p&gt;And here is the problem this step created. Every graphic now had to be built as a web layout, by a developer, in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step two: the bottleneck moves
&lt;/h2&gt;

&lt;p&gt;Porting one element from gtzip into a hand-coded web layout with animations took on average about a day and a half of developer time. A client's package is twenty to fifty of them. Multiply those and you get the real cost of every new client.&lt;/p&gt;

&lt;p&gt;But the worst part was not the throughput, it was the predictability. A six month plan collapsed the day a new client signed, because their graphics package jumped the queue and ate the developers who were supposed to be building features. We were not short of compute or short of ideas. We were short of a way to promise dates, and graphics production was the reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step three: Rive takes the layout work
&lt;/h2&gt;

&lt;p&gt;We moved graphics creation to Rive. A designer draws the graphic and wires up its state machine in the editor. The developer only maps data onto the view model, score to this field, team name to that one.&lt;/p&gt;

&lt;p&gt;One graphic went from about a day and a half of developer layout to about half a day of design work. Throughput settled at four to eight a day. And because it is design work now, it scales with outsourced designers, who cost two to three times less than developers. The bottleneck that had been breaking our plans was gone, and the developers went back to the product.&lt;/p&gt;

&lt;p&gt;It did not land cleanly. Our first integration of Rive on the web side was too greedy, and beta testing showed it adding thirty to forty milliseconds on top of what we already paid. We caught it on the bench, fixed it, and the graphics layer settled at forty to fifty milliseconds in total. That is one input carrying the whole package, not one source carrying a single lower third.&lt;/p&gt;

&lt;p&gt;It also closed the memory question from step one, though not in the way a tool comparison would suggest. Rive holds raster images perfectly well, and its own documentation warns that large ones eat device memory. Put that same five second sequence into Rive as frames and you pay again: in our practice around 300 to 500 MB at 1080p, better than 2.5 GB thanks to WebP compression, but the same order of problem.&lt;/p&gt;

&lt;p&gt;What changed was the default. Authoring in Rive means drawing the motion instead of recording it, so the animation becomes shapes, keyframes and a state machine, a few hundred kilobytes, and its footprint stops growing with duration or frame rate. The variable was never the tool. It was whether the animation is stored or computed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F00d9gf091ql9ny8fast5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F00d9gf091ql9ny8fast5.png" alt=" " width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This step created its own consequence, although it took a while to see it as one. A graphic was now a file with a state machine, driven by plain data. It did not need a browser to render. And it had never needed a GPU, we had just always rendered it through tools that came with one attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part worth taking away
&lt;/h2&gt;

&lt;p&gt;Look at what each step actually did. The web overlay took the graphics out of vMix's memory and made them testable, and in exchange it created a layout bottleneck. Rive removed the layout bottleneck, and quietly turned every graphic into a portable file.&lt;/p&gt;

&lt;p&gt;That last consequence is the one we did not plan for. We changed tools so that designers rather than developers would do the layout. What we got at the end of it was a graphic that no longer needed the tool it was drawn in: a file, a state machine, and some data to bind to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffoaqk5fyomxjovgi00iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffoaqk5fyomxjovgi00iu.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which left a question I could not put down. If a graphic does not need a browser to render, and never needed a GPU in the first place, what exactly is the GPU workstation still doing in a rented room next to every parallel broadcast? &lt;a href="https://dev.to/anovisoft/rendering-live-broadcast-graphics-without-a-gpu-and-what-four-hours-actually-cost-3c9l"&gt;I went and answered that.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am Andrei Novikov. I spent seven years running the engineering side of VSporte and I write about backend and realtime architecture. If you are at IBC and doing something adjacent, I am interested in comparing notes.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>performance</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
