<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>John Nunemaker</title><description>Thoughts on building software and software businesses. Owner of Box Out Sports and Very Good Software (Fireside, Flipper). Previously GitHub. Creator of HTTParty, Flipper, and more.</description><link>https://www.johnnunemaker.com/</link><language>en-us</language><atom:link href="https://www.johnnunemaker.com/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Friday Deploy: Changing the Wheels While the Car Is Moving</title><link>https://www.johnnunemaker.com/the-friday-deploy/</link><guid isPermaLink="true">https://www.johnnunemaker.com/the-friday-deploy/</guid><description>Garrett and I started a new podcast about shipping software with confidence. In episode one, we talk about rebuilding Fireside while it was live, including Postgres 9.5 to 18 in one hop.</description><pubDate>Thu, 01 Oct 2026 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Garrett and I started a podcast. It’s called &lt;a href=&quot;https://thefridaydeploy.fireside.fm&quot;&gt;The Friday Deploy&lt;/a&gt;, and the tagline is the whole point: ship on Friday, sleep through the night.&lt;/p&gt;
&lt;p&gt;We already do a marketing and business podcast for Fireside, so we figured, let’s go full on dev with this one. Feature flags, deployments, infrastructure, incidents, product decisions, and all the little practices that let you deploy whenever you want without the sweaty armpits. Sometimes it’ll be just me and Garrett, and sometimes we’ll bring on a guest to walk through what they do.&lt;/p&gt;
&lt;p&gt;Subscribe on &lt;a href=&quot;https://podcasts.apple.com/us/podcast/the-friday-deploy/id6816197157&quot;&gt;Apple Podcasts&lt;/a&gt;, &lt;a href=&quot;https://open.spotify.com/show/4tplJ47HVq7Yn4o07zjQzI&quot;&gt;Spotify&lt;/a&gt;, or &lt;a href=&quot;https://feeds.fireside.fm/thefridaydeploy/rss&quot;&gt;RSS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;episode-1-changing-the-wheels-while-the-car-is-moving&quot;&gt;Episode 1: Changing the Wheels While the Car Is Moving&lt;/h2&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/wKHjBfwC+s5MvqGP7&quot; title=&quot;Episode 1: Changing the Wheels While the Car Is Moving&quot; loading=&quot;lazy&quot; style=&quot;aspect-ratio: auto; height: 130px; color-scheme: light;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;We’re almost exactly two years into &lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/&quot;&gt;owning Fireside&lt;/a&gt;, so for the first episode we looked back at what we inherited and how we rebuilt nearly all of it without taking it down. Remember that meme of a car driving on two wheels while people hang out the side changing the other two? That’s basically been the last two years.&lt;/p&gt;
&lt;p&gt;Some of the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What We Inherited.&lt;/strong&gt; Fireside was eight years old when we bought it. Ruby 2.7, Rails 5, Postgres 9.5, and servers on a version of Ubuntu that had been dead for years. No Puppet, no Ansible, nothing that said “here’s how you recreate this.” Today almost none of that exists anymore. Garrett walked the app up through Ruby and Rails, and I swapped out every single server. The last of the old workers got retired the day before we recorded. (We talked about the early days of that cleanup on the &lt;a href=&quot;https://www.johnnunemaker.com/ruby-on-rails-podcast-taking-over-fireside-fm/&quot;&gt;Ruby on Rails Podcast&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Self-Documenting Infrastructure.&lt;/strong&gt; The process I keep coming back to: have the agent reverse engineer everything a server does into a markdown file, then tell it to recreate that on a brand new box with no downtime. Same thing for moving off Dan’s Cloudflare account. Document every setting that differs from the defaults, then rebuild it. I punted on that Cloudflare move for a year and eight months. With AI it was done in a sitting. I told the camper version of this story on &lt;a href=&quot;https://www.johnnunemaker.com/yagni-camping-chair-development/&quot;&gt;YAGNI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Postgres 9.5 to 18 in One Hop.&lt;/strong&gt; A sane person would have done this in a few jumps. We went from self-managed 9.5 to managed 18 in one shot. Everyone I asked for help just laughed. I waited months for the models to get better, ran the plan past something like six of them, and &lt;a href=&quot;https://www.johnnunemaker.com/shrinking-a-postgres-table/&quot;&gt;shrank a bloated table&lt;/a&gt; so 80 GB became about 20 GB and the copy only took ten minutes. Reads stayed up the whole time. Feeds and downloads kept working. Podcasters love their downloads, so that part was non-negotiable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flipper as the Big Red Button.&lt;/strong&gt; The go-live moment was flipping a database read-only flag. The whole app switched to read-only mode and showed a friendly message in the studio. I shut off the workers, did the migration, flipped the flag back, and let the workers chew through the queued downloads. Zero support emails. The scariest part was Codex deciding to compact for five minutes right before the switchover.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Taste Is Still the Job.&lt;/strong&gt; Garrett runs every plan past multiple models. Claude reviews Codex, Codex reviews Claude, Copilot reviews the PR. Fresh eyes without the session baggage catch things. But ask enough agents and you get a pile of opinions, and they will all happily over-engineer anything. Garrett’s agent once tried to add a feature flag to clean up a helper. Knowing what to say no to is &lt;a href=&quot;https://www.johnnunemaker.com/hallway-track-ai-taste/&quot;&gt;taste&lt;/a&gt;, and it’s what separates hacking around from shipping software you won’t regret.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prove It.&lt;/strong&gt; When we each asked AI to review months of our transcripts and suggest missing skills, the top one for both of us was some version of “prove it.” My biggest tip right now: when you feel anxious and keep adding more prompts to harden something, your problem isn’t the prompt. It’s that you haven’t figured out how to verify it. When I moved to Caddy, the agent tested the new certificates with curl and custom host headers before switching anything. I wouldn’t have even known I could test that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read-Only Production Context.&lt;/strong&gt; All our projects now have a read-only psql script the agent can use against a replica. When it starts overbuilding, I tell it to check our actual scale and then decide. Garrett does the same for UI work. How many customers have 20 podcasts? Not enough to need search in the podcast dropdown. Real data beats guessing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keep Deterministic Work Deterministic.&lt;/strong&gt; Garrett rebuilt &lt;a href=&quot;https://github.com/garrettdimon/reviewer&quot;&gt;Reviewer&lt;/a&gt; so agents can discover and run linters, tests, and security checks without burning tokens or freelancing CLI flags. Fewer degrees of freedom, more reliable outcomes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scheduled Tasks Are My Beating Heart.&lt;/strong&gt; Every morning I get a &lt;a href=&quot;https://flare.am&quot;&gt;Flare&lt;/a&gt; rundown across all our apps: traffic up or down, performance regressions, and what probably caused them. That’s how I found out a crawler was slurping half a million requests a day from one app. Then I wanted it for open source, then Stripe, then QuickBooks. Cron plus AI plus access to context is extremely powerful.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do We Even Need an Interface?&lt;/strong&gt; I haven’t opened the Flare web UI since the MCP started working. I just ask Codex what’s slow and it tells me. I floated &lt;a href=&quot;https://www.johnnunemaker.com/code-with-jason-people-buy-from-people/&quot;&gt;ops without a UI&lt;/a&gt; on Code with Jason, and now I’m seriously considering shipping Flare with no UI except a place to put your credit card. An alert is just a scheduled task. Garrett pushed it further: maybe the interface is assembled on the fly from a link, showing exactly the evidence for the thing that’s wrong and nothing else.&lt;/p&gt;
&lt;p&gt;We also got into letting agents carry work all the way to the final approval (I started a worker swap, forgot about it, and got a push notification hours later asking me to approve the cutover), optimistic versus pessimistic locking, and why a feature flag is not a million dollar bank transfer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://thefridaydeploy.fireside.fm/1&quot;&gt;Listen to episode one&lt;/a&gt;. If you’re the kind of person who wants to deploy on Friday and actually enjoy your weekend, &lt;a href=&quot;https://thefridaydeploy.fireside.fm/subscribe&quot;&gt;subscribe&lt;/a&gt;. We’re going to try and do this regularly.&lt;/p&gt;
</content:encoded><category>podcast</category><category>fireside</category><category>flipper</category><category>ai</category></item><item><title>YAGNI: Camping Chair Development</title><link>https://www.johnnunemaker.com/yagni-camping-chair-development/</link><guid isPermaLink="true">https://www.johnnunemaker.com/yagni-camping-chair-development/</guid><description>I joined Matt Swanson on YAGNI to talk about why I&apos;m not a craftsman anymore, rewriting Fireside&apos;s infrastructure from a camper, too many open agent loops, and why verification is now the hard part.</description><pubDate>Thu, 01 Oct 2026 16:00:00 GMT</pubDate><content:encoded>&lt;iframe src=&quot;https://share.transistor.fm/e/77f3a7b0&quot; title=&quot;YAGNI: Camping chair development w/ John Nunemaker&quot; loading=&quot;lazy&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;I joined &lt;a href=&quot;https://x.com/_swanson&quot;&gt;Matt Swanson&lt;/a&gt; on &lt;a href=&quot;https://yagni.fm/episodes/camping-chair-development-w-john-nunemaker&quot;&gt;YAGNI&lt;/a&gt; to talk about how I build software now across &lt;a href=&quot;https://fireside.fm&quot;&gt;Fireside&lt;/a&gt;, &lt;a href=&quot;https://www.flippercloud.io&quot;&gt;Flipper&lt;/a&gt;, and &lt;a href=&quot;https://boxoutsports.com&quot;&gt;Box Out&lt;/a&gt;. Some of it even happens from a camping chair.&lt;/p&gt;
&lt;p&gt;Some of the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I’m Not a Craftsman.&lt;/strong&gt; I always thought of myself as a craftsman. Bespoke furniture. Samurai. Honor. All that. Then on December 14th I turned on a 20x Claude plan just to try Opus and realized nope, I just love shipping stuff and solving problems. These days I read the data models and the queries because those affect how fast things are for customers. JavaScript and view code? I don’t read it. Does it look right? Is it responsive? What’s my Lighthouse score? Good enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stripping Back.&lt;/strong&gt; I went through a phase of plugins. Compound engineering, gstack, etc. Lately I’m removing things. The tools love to be perfectly correct and solve every theoretical race condition, and you end up with a ball of mutexes that gives me a stomach ache. Is it theoretically wrong? Yes. Does it ever happen in practice? I don’t think so. Less perfectionism, more shipping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rewriting Fireside’s Infrastructure From a Camper.&lt;/strong&gt; When we &lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/&quot;&gt;acquired Fireside&lt;/a&gt;, it was on super outdated Ubuntu and Postgres 9.5 with SSL handled by a tangle of Nginx, background jobs, and Redis. I asked what tool does all this and the answer was Caddy. Reverse engineer the current system into a markdown file, describe the new state, let it rip. I missed one host header. In three days I rewrote about 80% of our infrastructure while driving a camper six hours a day and sitting by a fire at night. I’m a scaredy cat about downtime, but it comes up with ways to smoke test everything before you flip the switch that I would never have done before.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brain or Hands.&lt;/strong&gt; Matt had a great framing: sometimes you’re the brain and the agent is the hands, and sometimes it flips. I hate being the hands, clicking through some cloud console because the agent told me to. So now I make a temporary API key that expires in an hour and let it do the work. Honestly, I want a new kind of key: read only, plus write access to anything it creates, for a limited time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Too Many Open Loops.&lt;/strong&gt; I want a hundred agents cranking on stuff for me all the time. But every agent tool shows you all of them, all the time, and each one sticks in the back of your brain. What I want is something like Railway’s canvas for agents. Every &lt;a href=&quot;https://www.johnnunemaker.com/conducting-rails/&quot;&gt;worktree&lt;/a&gt; is a box on an infinite canvas. Group the Flipper gem, Flipper Pro, and Flipper Cloud worktrees together, move the rest out of the way, and stop carrying it all in my head. I’m too lazy to build it. Someone please build it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prove It.&lt;/strong&gt; I had the agent go through my past chats and tell me what to turn into skills. Number one was &lt;code&gt;/prove&lt;/code&gt;: prove to me that what you did works all the way through. Then I ask how we can break it. Or I just gaslight it with “make &lt;a href=&quot;https://www.johnnunemaker.com/fewer-and-faster/&quot;&gt;fewer network calls&lt;/a&gt;” and it goes, “you’re right, I missed these N+1s.” Verification is now the biggest blocker and the hardest thing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fake Everything.&lt;/strong&gt; Matt brought up the idea of having agents build fake versions of third party APIs, like a vibe coded fake Slack that runs next to your app. No more booting on port 3000 so OmniAuth callbacks work. Simulate rate limits and outages with a flag. It reminded me of Toxiproxy from my GitHub availability days. Box Out is all social integrations, so we should totally do this for X and Meta.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Straight to Prod.&lt;/strong&gt; Garrett asked if we could finally set up staging for Fireside. I don’t use staging anymore. I want to get to prod as fast as I can, because that’s where I feel it now. Matt nailed this: the flow and satisfaction didn’t go away, it just happens at a different point in the process. It used to be when the code was clean. Now it’s when the thing is live and people are using it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Talking All Day.&lt;/strong&gt; I’ve had &lt;a href=&quot;https://www.johnnunemaker.com/pain-and-programming/&quot;&gt;hand and arm problems&lt;/a&gt; my whole programming life. Now I talk to my agents all day with Wispr Flow. My only problem is a sore throat. If anything, AI has prolonged my career.&lt;/p&gt;
&lt;p&gt;We also got into Cloudflare Tunnel for checking work from my phone, proving to an iCal provider that their feeds were broken (zero bytes since the day they launched their new thing), and why feature flags and APMs matter more when nobody reads the code. APMs are going to have to get a lot cheaper.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://yagni.fm/episodes/camping-chair-development-w-john-nunemaker&quot;&gt;Listen to the full episode on YAGNI&lt;/a&gt;. I hope you enjoy it. If you want more, I talked about taste and AI on &lt;a href=&quot;https://www.johnnunemaker.com/hallway-track-ai-taste/&quot;&gt;The Hallway Track&lt;/a&gt; last month.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2026-10-01&lt;/strong&gt;: Garrett and I went deeper on the Fireside rebuild, including Postgres 9.5 to 18 in one hop with no downtime for listeners, in episode one of our new podcast, &lt;a href=&quot;https://www.johnnunemaker.com/the-friday-deploy/&quot;&gt;The Friday Deploy&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>podcast</category><category>ai</category></item><item><title>The Hallway Track: Why AI Rewards People Who Already Have Taste</title><link>https://www.johnnunemaker.com/hallway-track-ai-taste/</link><guid isPermaLink="true">https://www.johnnunemaker.com/hallway-track-ai-taste/</guid><description>I joined The Hallway Track to talk about running multiple companies, how feature flags change the way you build, and why taste matters more in the AI era.</description><pubDate>Wed, 26 Aug 2026 16:00:00 GMT</pubDate><content:encoded>&lt;iframe src=&quot;https://www.youtube.com/embed/Ph4kuAZdHcc?feature=oembed&quot; title=&quot;Why AI Rewards People Who Already Have Taste&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;I joined Chris on &lt;a href=&quot;https://www.youtube.com/watch?v=Ph4kuAZdHcc&quot;&gt;The Hallway Track&lt;/a&gt; to talk about running &lt;a href=&quot;https://boxoutsports.com&quot;&gt;Box Out Sports&lt;/a&gt;, &lt;a href=&quot;https://fireside.fm&quot;&gt;Fireside&lt;/a&gt;, and &lt;a href=&quot;https://www.flippercloud.io&quot;&gt;Flipper&lt;/a&gt; while still maintaining open source projects like &lt;a href=&quot;https://github.com/jnunemaker/httparty&quot;&gt;HTTParty&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We covered a lot of ground in 50 minutes: why I gave up trying to focus, the production problem that led to Flipper, how feature flags change the way teams build software, and why taste might be the real advantage in the AI era.&lt;/p&gt;
&lt;p&gt;Some of the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Giving Up on Focus.&lt;/strong&gt; I spent years feeling like I was broken because I couldn’t focus on one thing. Everyone tells you focus is how you do something big and great, but I like having a lot of things going. If I get jammed on one project, I can switch to the next most important thing on another instead of dropping to zero. I don’t push one thing forward as far or as fast, but I push a lot of things forward regularly. I finally gave up trying to be someone else about three years ago.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What AI Changed at Box Out.&lt;/strong&gt; The biggest change is amplification. We have shipped so much in the last six months. But we’re also doing things we would have just said no to before. For years Box Out was built for speed, not customization. Recreating Photoshop in the browser was way outside our niche and not worth the time. Now we’re building a Figma or Photoshop-style template editor because, well, what if we did both?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Scaling Crisis That Led to Flipper.&lt;/strong&gt; While working on Words With Friends, we were having scaling problems because a bunch of celebrities started playing and traffic went nuts. I kept rolling out a new caching system and taking down the site because the cache was cold. Then we tried a percentage rollout. I went from 1% to 5% until the cache was warm enough and then let it rip. Feature flags were amazing, but the library we used only supported Redis. I built Flipper so your flags could live in Active Record, environment variables, a file on disk, or whatever made sense for your application.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Feature Flags Change How You Build.&lt;/strong&gt; Technically a flag is just a quick check to see if something is on or off. But once people start using them, you have to pry them out of their cold dead fingers. You can get unfinished work into production, let the right people try it, and turn it off without another deploy. Everything gets easier, less stressful, and less scary. Chris shared an old newspaper phrase I loved: “demos over memos.” Just get something on a screen that people can react to. If it’s behind a flag, who cares? Nobody sees it. You didn’t break anything. It’s fine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Maintaining Open Source With AI.&lt;/strong&gt; I get much better pull requests for HTTParty now. They show up with tests and are often pretty close to ready to ship. AI also helps me research what to work on next and triage security reports. Half the time I read one of those reports and think, bro, I don’t even know what language this is. Now I can understand it, figure out if it’s real, and release CVE fixes faster. That makes a huge difference for a project I maintain in my spare time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Taste Is the Advantage.&lt;/strong&gt; Everyone I see exploding with AI already had taste and ideas. They were good without it. They were just constrained by time, brainstorming, research, and all the other stuff around creating a product. AI amplifies that by a different multiplier. It also amplifies bad taste and lets dysfunctional teams make a mess ten times faster. The building was never the hard part. Figuring out what to build was.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building Games With My Son.&lt;/strong&gt; We started with AI-generated coloring pages and bedtime stories. Then we made Chickens vs. Zombies, where chickens shoot eggs out of their butts to kill zombies. Obviously. From there we built a Minecraft-ish game with 3D worlds, chat, portals, and Cloudflare Durable Objects. Neither of us had ever made a game. Now he can build what’s in his imagination, play it with his friends, and learn the same things I do when I build software: ask questions, prove that it works, and keep making it better. He used to say he wanted to be an inventor. Now he says he’s going to be a programmer.&lt;/p&gt;
&lt;p&gt;We also got into turning open source into a business, the future of runtime controls in Flipper, why AI exposes dysfunction inside engineering teams, and what programming may look like for the next generation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Ph4kuAZdHcc&quot;&gt;Watch the full conversation on YouTube&lt;/a&gt;. I hope you enjoy it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2026-10-01&lt;/strong&gt;: Garrett and I dug into taste, over-engineering agents, and verification in episode one of our new podcast, &lt;a href=&quot;https://www.johnnunemaker.com/the-friday-deploy/&quot;&gt;The Friday Deploy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2026-10-01&lt;/strong&gt;: I went deeper on how I actually build with AI now on &lt;a href=&quot;https://www.johnnunemaker.com/yagni-camping-chair-development/&quot;&gt;YAGNI&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>podcast</category><category>business</category><category>ai</category></item><item><title>Code with Jason: People Buy From People</title><link>https://www.johnnunemaker.com/code-with-jason-people-buy-from-people/</link><guid isPermaLink="true">https://www.johnnunemaker.com/code-with-jason-people-buy-from-people/</guid><description>I went on Code with Jason for the second time. Jason and I got into the Fireside acquisition, how to actually find and finance a business to buy, why…</description><pubDate>Mon, 01 Jun 2026 18:47:54 GMT</pubDate><content:encoded>&lt;p&gt;I went on &lt;a href=&quot;https://www.codewithjason.com/podcast/19168361-320-john-nunemaker-of-fireside-fm-box-out-sports-and-very-good-software/&quot;&gt;Code with Jason&lt;/a&gt; for the second time. Jason and I got into the Fireside acquisition, how to actually find and finance a business to buy, why support is a product, and where I think developer tools are headed in the AI era.&lt;/p&gt;
&lt;p&gt;Some of the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why I Bought Fireside.&lt;/strong&gt; Complete happenstance. I was already paying Garrett Dimon to push Flipper forward, and Garrett had worked on Fireside for Dan Benjamin back in the day. Dan had lost interest and was trying to sell, but it was too big for the small players and too small for the big ones. The math was simple: if I bought it, the profit could pay for Garrett to work on both Fireside and Flipper instead of it coming out of my pocket every month. I’m a long-term person, podcasts aren’t slowing down, and it lined up with the analytics and content hosting I’d done before with Gauges and Harmony. So we did it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finding Deals.&lt;/strong&gt; The marketplaces (Quiet Light, FE International, acquisition.com) are mostly where people list a dying SaaS expecting four to eight times multiples. That’s not reality. A declining SaaS is more like 1.5 to 2.25x. The deals that actually work come through your network, someone who knows someone quietly looking to sell. Stick to what you know. And since the paperwork is identical whether the thing makes fifty thousand or five million, you might as well take the bigger swing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Financing It.&lt;/strong&gt; You don’t need a pile of cash. My house was paid off, so I borrowed against the equity. Banks know houses cold, so they’ll lend up to 80% the next day, no questions asked. Farmland is more like 50%. SBA loans were running 10 to 12% at the time versus 5 to 6% for a bank loan, so the margin matters. I took a 15-year term for the low payment even though I plan to pay it off in five to eight. It forces the business to clear at least that much profit, and then it just quietly pays for itself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;People Buy From People.&lt;/strong&gt; Right now Fireside’s edge is simple: Garrett and I do the support and build the product. If you send me the right request and I can knock it out fast, I’ll ship it before I even reply. Most customers aren’t technical (lots of Linux shows and religious orgs), and they value a real person who’ll hop on a Zoom and fix their DNS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing to the People You Already Have.&lt;/strong&gt; Churn is around 2% and most of the focus has been telling existing customers we’re listening and shipping. Churn is a trailing indicator. By the time someone leaves, it’s too late to do anything about it. So we get ahead of it. The more aggressive growth (conferences, underserved niches) is the next wave.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Onboarding and Retention Are the Same Coin.&lt;/strong&gt; Frictionless onboarding helps the self-serve people and the hand-held people at the same time. Every time you onboard someone manually, automate a little more of it so the next one is easier. I just rebuilt Flipper’s migration to be one click from the UI, the CLI, or the console. So slippery you slide right down the waterfall, and then you’re pulling out your credit card wondering what just happened.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A Scrappy, Opinionated APM.&lt;/strong&gt; I’m building a lightweight APM (I called it Caboose on the show, it’s Flare now). The trick is that being opinionated makes it cheap. The expensive tools store everything so you can ask any question later. I’d rather pre-compute the answers to the questions you actually ask: count, sum, and error count per endpoint and job, the network breakdown (db, view, cache), and a handful of samples of slow requests. That solves 80 to 90% of performance problems for ten to fifty bucks a month instead of New Relic pricing that explodes the moment you add a teammate. This comes straight from my GitHub years doing analytics, statsd dashboards, and the Datadog migration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ops Without a UI.&lt;/strong&gt; Honestly you barely need a dashboard. You want an API, a CLI, and skills or MCP so Claude can speak your language and pull the data. I did this with Flipper: dumped the gate data and 30 days of telemetry, asked Claude which flags I could delete, and cleared out about 15 stale flags and 600 lines of code in one pass. That’s the moment I knew I wanted the same thing for the APM. Knowing what’s happening in production and shipping safely matters more every month as people read less of the code themselves. GitHub Scientist style stuff, running two code paths and comparing them, is next on my radar.&lt;/p&gt;
&lt;p&gt;We also got into Riverside versus Descript, why trying to do recording, editing, and hosting all at once turns into the PDA of old, being friends with your competitors, and my current obsession with Railway.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;bookmark&quot; href=&quot;https://www.codewithjason.com/podcast/19168361-320-john-nunemaker-of-fireside-fm-box-out-sports-and-very-good-software/&quot;&gt;&lt;span class=&quot;bookmark-title&quot;&gt;320 - John Nunemaker of Fireside.fm, Box Out Sports and Very Good Software - The Code with Jason Podcast&lt;/span&gt;&lt;span class=&quot;bookmark-description&quot;&gt;In this episode I talk with John Nunemaker about his journey with Ruby, acquiring Fireside.fm, and his ventures in software focused on podcast hosting and feature flag services. We also explore the potential impacts of AI in the development space and John’s vision for the future.Links:- Box Out Sports- Very Good Software- Flipper Cloud- Fireside.fm- Nonsense Monthly&lt;/span&gt;&lt;span class=&quot;bookmark-domain&quot;&gt;codewithjason.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2026-10-01&lt;/strong&gt;: I’ve stopped opening Flare’s web UI entirely and just ask my agent what’s slow. I talked about maybe shipping it with no UI at all on &lt;a href=&quot;https://www.johnnunemaker.com/the-friday-deploy/&quot;&gt;The Friday Deploy&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>IndieRails Podcast: The Conductor</title><link>https://www.johnnunemaker.com/indierails-podcast-the-conductor/</link><guid isPermaLink="true">https://www.johnnunemaker.com/indierails-podcast-the-conductor/</guid><description>I hopped on IndieRails with Jess and Jeremy (again). We covered a lot of ground in about 90 minutes. Quick business catch up and then dove into how AI has…</description><pubDate>Thu, 19 Mar 2026 19:11:23 GMT</pubDate><content:encoded>&lt;p&gt;I hopped on &lt;a href=&quot;https://www.indierails.com/75&quot;&gt;IndieRails with Jess and Jeremy&lt;/a&gt; (&lt;a href=&quot;https://www.johnnunemaker.com/indie-rails/&quot;&gt;again&lt;/a&gt;). We covered a lot of ground in about 90 minutes. Quick business catch up and then dove into how AI has changed pretty much everything about how I work.&lt;/p&gt;
&lt;p&gt;Some of the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Business Updates&lt;/strong&gt;. Flipper Cloud almost doubled revenue last year, with most of the growth in the last few months. No AI headwinds on docs or conversion. Fireside is stabilizing — we flattened churn and had our first three month stretch of even or growing customers since taking it over. Momentum, the coworking space I invested in, is filling up and becoming a real community in South Bend.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Following the Inspiration&lt;/strong&gt;. I’m a mood person. I follow the energy. Having multiple products at different stages (five, six, and seven figures) means there’s always something that matches whatever I’m feeling that day. I’ve spent 20 years intentionally building toward that flexibility.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Support-Driven Development&lt;/strong&gt;. With Fireside, I’m close to the customer again. Someone asks for a responsive player, I build one from scratch in three days. Someone wants playlists, done. Someone wants custom colors saved, done in an hour. They’re blown away because the product had been dormant. That feedback loop is addicting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Company Brain&lt;/strong&gt;. For Box Out, I’m building an internal AI system using LibreChat with MCPs for our read replica database, Stripe, and a custom internal API. The goal is letting our small team query business data naturally — hydrate conference attendee lists, look up support patterns, pull subscriber counts. Eventually I’ll wire in Metabase too for the verified reports.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Working Styles&lt;/strong&gt;. Jeremy, Jess, and I got into how different developers use AI differently. Garrett goes heavy on docs and specs and skills. I go vanilla — whisper flow, let it roll, see what happens. Both approaches work. A lion doesn’t concern himself with tokens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Arbitrage&lt;/strong&gt;. There’s a window right now where you can get significantly more done. Not just a little more — I’d say I’m working 1.3-1.5x the hours but shipping 10x. That won’t last forever, but right now the gap between people using these tools and people who aren’t is massive. And we’re still just the nerds. Most people haven’t even tried a chatbot yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What’s Next&lt;/strong&gt;. I think the AI era means more people shipping more code, which means more demand for developer tools — monitoring, debugging, feature flags, experiment frameworks. That’s why I’m building an APM tool and planning to build something like GitHub Scientist next. The incumbents have no incentive for you to send less data. I think there’s room for opinionated, affordable, AI-friendly developer tools.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conductor in the Web&lt;/strong&gt;. What I really want is my dev environment on a server somewhere, always on, accessible from my phone. Spin up workspaces, prompt the next thing, check in from the couch or car line. Someone’s going to solve this well in the next couple months. I’d pay as much as I do for Claude for that solution.&lt;/p&gt;
&lt;p&gt;We also got into the health and sustainability of all this, the farming lifestyle analogy (Jeremy and I both grew up in farm country), consulting economics in the AI era, and whether developers should be pushing harder toward ownership.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.indierails.com/75&quot;&gt;Listen here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Codex remote access turned out to be most of what I wanted. My already set up Mac sits on my desk and I fire off commands from my phone, even from a camping chair. I talked about it on &lt;a href=&quot;https://www.johnnunemaker.com/yagni-camping-chair-development/&quot;&gt;YAGNI&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>Rails Business Podcast (again)</title><link>https://www.johnnunemaker.com/rails-business-podcast-again/</link><guid isPermaLink="true">https://www.johnnunemaker.com/rails-business-podcast-again/</guid><description>How AI has changed my day-to-day as a developer.</description><pubDate>Thu, 05 Mar 2026 20:14:06 GMT</pubDate><content:encoded>&lt;p&gt;I joined Brendan Buckingham and Ryan Frisch on the &lt;a href=&quot;https://www.railsbusiness.com/2435951/episodes/18785602-john-nunemaker-on-ai-development&quot;&gt;Rails Business Podcast&lt;/a&gt; to talk about how AI has changed my day-to-day as a developer.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;bookmark&quot; href=&quot;https://www.railsbusiness.com/2435951/episodes/18785602&quot;&gt;&lt;span class=&quot;bookmark-title&quot;&gt;John Nunemaker on AI Development - Rails Business&lt;/span&gt;&lt;span class=&quot;bookmark-description&quot;&gt;John Nunemaker returns to discuss how fast AI tooling has changed and argues tech leaders should adopt Claude Max (defaulting to Opus), set up agent-friendly local environments, and roll that out to their teams. He shares how his company built an…&lt;/span&gt;&lt;span class=&quot;bookmark-domain&quot;&gt;railsbusiness.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here are the highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your job as a tech leader is to go first.&lt;/strong&gt; Get Claude Code with Opus, set up your local dev environment to be agent-friendly, then do the same for everyone on your team. I told everyone to get the $100 Max plan and offered to pay for it myself if they didn’t think it was worth it. No one’s taken me up on that.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Brain,” an AI-in-a-box for the company.&lt;/strong&gt; I built an internal tool on a cheap Hetzner server using LibreChat, Postgres MCP (read-only replica), Stripe MCP, and a custom support MCP. Non-technical teammates can now ask natural language questions about customers, support trends, and revenue data without going through me. Secured it all behind Tailscale.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The support insights were eye-opening.&lt;/strong&gt; By slurping all our Crisp support conversations into a database and hooking it up as an MCP, I could ask things like “summarize the last week of support requests” and “what’s the tone of our support person?” and get real answers. Next step is cron jobs that automatically post weekly summaries to Slack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claude as a code review spin cycle.&lt;/strong&gt; Team members now run Claude review locally, fix issues, then run &lt;code&gt;@claude&lt;/code&gt; review on the GitHub PR before requesting human review. By the time it gets to me, it’s usually ready to merge. This solved the bottleneck of everyone suddenly producing several PRs a day.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.conductor.build/&quot;&gt;&lt;strong&gt;Conductor&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;changed the game for parallel work.&lt;/strong&gt; It manages isolated worktrees with separate databases, ports, and sessions. I can work on 3-5 things simultaneously, like a feature, a bug from Honeybadger, a support request, each in its own workspace. Setup and teardown scripts handle the isolation (fewer than 100 lines of code per app).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;People who couldn’t write Rails before now can.&lt;/strong&gt; &lt;a href=&quot;https://zastrow.co/&quot;&gt;Phillip&lt;/a&gt;, who we brought on for React/HTML, is now consistently making solid Rails PRs. Claude bridges the gap. The first PR needed some guidance on resiliency patterns, but after that, the spin cycle workflow handles it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caddy for local HTTPS and custom domains.&lt;/strong&gt; Drop it in your Procfile, point wildcard subdomains at it, and you get HTTPS locally with custom domain support. Solved a bunch of pain around cookies, CORS, and multi-workspace development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stay bullish.&lt;/strong&gt; Software engineering jobs are reportedly up about 4.5% month over month. There’s an arbitrage window right now for teams that adopt these tools early. Don’t get behind. That’s the worst place to be.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>podcast</category></item><item><title>Conducting Rails</title><link>https://www.johnnunemaker.com/conducting-rails/</link><guid isPermaLink="true">https://www.johnnunemaker.com/conducting-rails/</guid><description>A practical guide to running Ruby on Rails across parallel Conductor workspaces, including ports, databases, setup scripts, CORS, and cleanup.</description><pubDate>Fri, 30 Jan 2026 18:01:29 GMT</pubDate><content:encoded>&lt;h2 id=&quot;in-short&quot;&gt;In short&lt;/h2&gt;
&lt;p&gt;Conductor creates isolated workspaces for running multiple coding-agent sessions in parallel. To make that model reliable with Rails:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Copy required gitignored files into each workspace.&lt;/li&gt;
&lt;li&gt;Derive ports, hosts, cookies, and generated URLs from &lt;code&gt;CONDUCTOR_PORT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Give every workspace its own development and test databases.&lt;/li&gt;
&lt;li&gt;Automate setup, startup, and teardown scripts.&lt;/li&gt;
&lt;li&gt;Account for shared services such as S3 and make each browser tab identifiable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ve been using &lt;strong&gt;@conductor_build&lt;/strong&gt; heavily and it’s completely changed how I ship Ruby on Rails code when working with Claude models.&lt;/p&gt;
&lt;p&gt;The multi-workspace, multi-process model feels unusual at first compared to a single editor flow, but once you handle the Rails-specific quirks, your ability to work in parallel and ship faster skyrockets.&lt;/p&gt;
&lt;p&gt;Here are the key practical steps and fixes I’ve found essential for getting a Rails app running reliably across multiple Conductor workspaces. I’ll try to keep this up to date as I find new things.&lt;/p&gt;
&lt;h2 id=&quot;copy-essential-gitignored-files&quot;&gt;Copy essential gitignore’d files&lt;/h2&gt;
&lt;p&gt;Anything in &lt;code&gt;.gitignore&lt;/code&gt; (credentials, &lt;code&gt;.env.local&lt;/code&gt;, custom config files, active storage files in &lt;code&gt;tmp/&lt;/code&gt; etc.) won’t copy automatically. Manually &lt;code&gt;cp&lt;/code&gt; these from your main &lt;code&gt;CONDUCTOR_ROOT&lt;/code&gt; project directory into each workspace directory during initial setup. This keeps isolation clean without git&lt;br&gt;
pollution.&lt;/p&gt;
&lt;h2 id=&quot;drive-everything-through-conductor_port&quot;&gt;Drive everything through &lt;code&gt;CONDUCTOR_PORT&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Conductor assigns dynamic ports—make your app fully aware of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prefer &lt;code&gt;ENV[&apos;CONDUCTOR_PORT&apos;]&lt;/code&gt; with a fallback (e.g., 3000).&lt;/li&gt;
&lt;li&gt;Update Action Mailer &lt;code&gt;default_url_options&lt;/code&gt;, controller/view host generation, and any internal URL building to use the current host + port.&lt;/li&gt;
&lt;li&gt;Scope sessions and cookies by host + port to prevent collisions across workspaces.&lt;/li&gt;
&lt;li&gt;A solid starting point for host and port handling is in &lt;a href=&quot;https://gist.github.com/jnunemaker/7e4b909bce0bb8796d342bed06bd4c3e&quot;&gt;in this Gist&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;isolate-databases-for-parallel-execution&quot;&gt;Isolate databases for parallel execution&lt;/h2&gt;
&lt;p&gt;Shared test databases cause lock errors when running specs/tests concurrently across workspaces. Solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a per-workspace test database (suffix by workspace ID, &lt;code&gt;CONDUCTOR_PORT&lt;/code&gt;, or Rails test env number).&lt;/li&gt;
&lt;li&gt;Archive/drop the DB on workspace close.&lt;/li&gt;
&lt;li&gt;For dev, if you create new dbs, seed them in the conductor setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-setup-run-and-teardown-scripts&quot;&gt;Use setup, run, and teardown scripts&lt;/h2&gt;
&lt;p&gt;Conductor supports these hooks natively. Automate workspace preparation (DB setup, seeding, file copying), server startup, and cleanup. This makes spinning up and tearing down consistent, repeatable, and fast.&lt;/p&gt;
&lt;p&gt;Create &lt;code&gt;bin/conductor-setup&lt;/code&gt; (or just mod &lt;code&gt;bin/setup&lt;/code&gt; to work differently when conductor &lt;code&gt;ENV&lt;/code&gt; vars are present) and &lt;code&gt;bin/conductor-teardown&lt;/code&gt; (for when archive happens). &lt;code&gt;run&lt;/code&gt; can just be &lt;code&gt;bin/dev&lt;/code&gt; or whatever you use.&lt;/p&gt;
&lt;h2 id=&quot;cors-direct-uploads&quot;&gt;CORS (direct uploads)&lt;/h2&gt;
&lt;p&gt;One other issue is direct uploads to S3 and similar services. You’ll want to be sure to use a dev bucket that allows any host/port.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;aws&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; s3api&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; put-bucket-cors&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --bucket&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; your-bucket-dev&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --region&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; us-east-1&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --cors-configuration&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &apos;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  &quot;CORSRules&quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;      &quot;AllowedHeaders&quot;: [&quot;*&quot;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;      &quot;AllowedMethods&quot;: [&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;HEAD&quot;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;      &quot;AllowedOrigins&quot;: [&quot;*&quot;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;      &quot;MaxAgeSeconds&quot;: 3000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;}&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;rename-browser-tabs&quot;&gt;Rename browser tabs&lt;/h2&gt;
&lt;p&gt;Last but not least, rename your browser tabs. Trying to remember which port goes to which workspace is annoying. Just rename it once you open it to whatever the workspace is and you’ll be golden.&lt;/p&gt;
&lt;h2 id=&quot;the-shift&quot;&gt;The Shift&lt;/h2&gt;
&lt;p&gt;The mindset shift to multiple concurrent processes and workspaces is the biggest hurdle. Once it clicks and your app behaves correctly across them, the productivity gain is massive. If you run into Rails-specific issues (subdomains, shared resources, etc.), the fixes are usually straightforward. Just ask claude/conductor how to fix them by updating the bin scripts I mentioned above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conductor + Claude Opus has mostly replaced my editor for day-to-day work. I only fall back to a traditional editor for quick muscle-memory tasks.&lt;/li&gt;
&lt;li&gt;The GitHub flow of Create PR &amp;gt; Run CI &amp;gt; Fix CI Failures &amp;gt; Merge is SICK.&lt;/li&gt;
&lt;li&gt;Every support request or thought that pops in my head becomes a workspace.&lt;/li&gt;
&lt;li&gt;Heavy usage quickly justifies upgrading your Claude plan if you’re on a lighter tier. The combination of claude + conductor unlocks a lotta throughput.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re building with Rails and leaning on Claude heavily, Conductor is worth the initial setup effort. The payoff in shipping speed is real.&lt;/p&gt;
&lt;p&gt;Always happy to brainstorm fixes for any Rails gotchas you hit—just reach out.&lt;/p&gt;
</content:encoded></item><item><title>Rooted &amp; Reaching Podcast Interview</title><link>https://www.johnnunemaker.com/rooted-reaching-podcast-interview/</link><guid isPermaLink="true">https://www.johnnunemaker.com/rooted-reaching-podcast-interview/</guid><description>I recently sat down with Marty Mechtenberg on the Rooted and Reaching podcast to talk about my entrepreneurial journey, from struggling through my first…</description><pubDate>Fri, 23 Jan 2026 19:33:23 GMT</pubDate><content:encoded>&lt;iframe src=&quot;https://www.youtube.com/embed/nHBXcz-U9WA?feature=oembed&quot; title=&quot;Rooted &amp; Reaching: Building with Intention: Craft, Code, and Community with John Nunemaker&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;I recently sat down with Marty Mechtenberg on the Rooted and Reaching podcast to talk about my entrepreneurial journey, from struggling through my first programming class at Bethel to building multiple SaaS businesses while staying rooted in the South Bend area.&lt;/p&gt;
&lt;h2 id=&quot;the-early-days-learning-to-code-the-hard-way&quot;&gt;The Early Days: Learning to Code (the Hard Way)&lt;/h2&gt;
&lt;p&gt;I wasn’t a natural programmer. In my sophomore year at Bethel, I was pulling a D in my programming class while my future business partner Steve would walk in, hand in his homework, and leave. I spent hours in office hours, terrified of failure after a lifetime of straight A’s. But that struggle taught me something important: once I learned something the hard way, it stuck.&lt;/p&gt;
&lt;p&gt;What really hooked me was the internet. The moment I could make something and have my mom see it by typing a URL into her browser, that was magic. That’s when programming stopped being abstract loops on a screen and became something I couldn’t stop doing.&lt;/p&gt;
&lt;h2 id=&quot;ordered-list-and-the-power-of-sharing&quot;&gt;Ordered List and the Power of Sharing&lt;/h2&gt;
&lt;p&gt;After Notre Dame, I joined my friend Steve Smith at Ordered List, a small agency. We had a simple philosophy: talk about everything we built. We blogged about our process, spoke at conferences, and contributed to open source. We weren’t trying to be clever about marketing, it was just what we knew how to do.&lt;/p&gt;
&lt;p&gt;That openness led to opportunities we never expected. Speaking at a Ruby conference in New Orleans, I reconnected with a friend who had started GitHub. One conversation led to another, and eventually GitHub acquired our five-person team in 2011.&lt;/p&gt;
&lt;h2 id=&quot;the-github-years-and-why-i-left&quot;&gt;The GitHub Years (and Why I Left)&lt;/h2&gt;
&lt;p&gt;GitHub was an incredible ride—from 45 employees to over a thousand in just four years. But as the company grew, so did the layers between me and any real decision-making power. By 2016-17, I was seven layers deep and itching to get back to building things my own way.&lt;/p&gt;
&lt;p&gt;When Microsoft acquired GitHub in 2019, I took my exit. I needed to reclaim my indie spirit.&lt;/p&gt;
&lt;h2 id=&quot;building-for-flexibility-not-fortune&quot;&gt;Building for Flexibility, Not Fortune&lt;/h2&gt;
&lt;p&gt;Today I run multiple products: Box Out Sports (sports graphics for schools), Flipper (feature flags for developers), and Fireside (podcast hosting). The common thread? I’ve always optimized for flexibility over maximum revenue.&lt;/p&gt;
&lt;p&gt;I watched my dad work 90-hour weeks on the farm. I wanted the freedom to take a seven-week camping trip in the summer.&lt;/p&gt;
&lt;p&gt;My advice for aspiring entrepreneurs: work your tail off in your 20s across different environments. Figure out what you actually like. Then optimize for the life you want, not just the biggest paycheck.&lt;/p&gt;
&lt;h2 id=&quot;why-south-bend&quot;&gt;Why South Bend?&lt;/h2&gt;
&lt;p&gt;People ask why I didn’t move to San Francisco. The answer is simple: South Bend has everything I need. Good restaurants, Notre Dame athletics, a reasonable cost of living, no brutal traffic. It’s big enough to have what matters, small enough to avoid what doesn’t.&lt;/p&gt;
&lt;p&gt;Plus, there’s something special here I didn’t expect to find: South Bend had its own watch company in the early 1900s, making precision pocket watches for the railroad industry. I’ve become obsessed with finding and restoring these watches—physical artifacts I can pass down to my kids, unlike software that rots in three years without constant care.&lt;/p&gt;
&lt;h2 id=&quot;the-ai-era&quot;&gt;The AI Era&lt;/h2&gt;
&lt;p&gt;I’m not worried about AI taking over. I’m obsessed with it. It’s made me multilingual as a programmer. I can now contribute to Go projects despite being a Ruby developer for 20 years. The fundamentals I learned the hard way? They translate perfectly to telling Claude or ChatGPT exactly what I need.&lt;/p&gt;
&lt;p&gt;The key is knowing what to ask for. Twenty years of programming principles don’t disappear, they become the foundation for working with AI effectively.&lt;/p&gt;
&lt;p&gt;Hope you enjoy!&lt;/p&gt;
</content:encoded><category>business</category><category>podcast</category></item><item><title>What makes you different</title><link>https://www.johnnunemaker.com/what-makes-you-different/</link><guid isPermaLink="true">https://www.johnnunemaker.com/what-makes-you-different/</guid><description>Something that&apos;s been on my mind lately: Why is a customer going to choose my product? There&apos;s tens to hundreds or even thousands (looking at you CRM&apos;s) of…</description><pubDate>Mon, 13 Oct 2025 14:39:27 GMT</pubDate><content:encoded>&lt;p&gt;Something that’s been on my mind lately: &lt;strong&gt;Why is a customer going to choose my product&lt;/strong&gt;? There’s tens to hundreds or even thousands (looking at you CRM’s) of every app for every problem. Why would someone choose mine?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Price?&lt;/strong&gt; I’m a &lt;a href=&quot;https://blog.flippercloud.io/per-seat-pricing-sucks/&quot;&gt;firm believer&lt;/a&gt; in charging a price that works for the customer &lt;strong&gt;and&lt;/strong&gt; for you. Competing on price is a race to the bottom. If this is where you are at, you’ve already lost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features?&lt;/strong&gt; Maybe but that’s a grind and a bit whack-a-mole. Having all the features someone could ever want waters down a product. Honestly, it makes products confusing. How do you build work flow and create value for the customer when the customer is anyone and the work flow is anything?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Something else?&lt;/strong&gt; I’m becoming a bit obsessed with what makes you different. &lt;em&gt;People remember different&lt;/em&gt;. And when someone gets out their card to buy something, you want them to remember you.&lt;/p&gt;
&lt;p&gt;Our brains love to live on autopilot in a sea of sameness. This makes us hyper-sensitive to different. Even if that weren’t true, different is great because it makes comparison difficult. Instead of granny smith verse golden delicious, it’s apples and oranges.&lt;/p&gt;
&lt;h2 id=&quot;the-hot-dog&quot;&gt;The Hot Dog&lt;/h2&gt;
&lt;p&gt;In Unreasonable Hospitality, Will Guidara recounts the story of one particular table of diners at Eleven Madison. They were foodies in New York from overseas to enjoy the best restaurants.&lt;/p&gt;
&lt;p&gt;They’d probably had several amazing experiences. But one of them mentioned &lt;strong&gt;they were bummed they didn’t get a new york hot dog&lt;/strong&gt;. This was their last night in the city, so Will ran to the nearest hot dog cart, got a dog and convinced his chef to serve it to them.&lt;/p&gt;
&lt;p&gt;Of all the places they dined, who do you think they remembered? Which story do you think they told people over and over? The hot dog.&lt;/p&gt;
&lt;p&gt;Different is remembered. Different is shared. It’s better than being better. And that’s why I can’t stop thinking about what makes my products different.&lt;/p&gt;
&lt;h2 id=&quot;an-example&quot;&gt;An Example&lt;/h2&gt;
&lt;p&gt;Let’s talk about &lt;a href=&quot;https://boxoutsports.com&quot;&gt;Box Out&lt;/a&gt; for a moment as a practical example.&lt;/p&gt;
&lt;p&gt;Our competition focuses on &lt;em&gt;infinite customization&lt;/em&gt;. Move this logo wherever you want or make it bigger. Change the font or text size. Drag this. Drop that. All of them just re-create Photoshop in the browser with a bunch of stock templates to choose from. Heck, that is all canva is.&lt;/p&gt;
&lt;p&gt;We do the opposite. We focus on &lt;strong&gt;speed&lt;/strong&gt; (time to social timeline) and &lt;strong&gt;brand&lt;/strong&gt; (&lt;a href=&quot;https://boxoutsports.com/features/manage-users-with-set-it-and-forget-it-permissions&quot;&gt;delegate&lt;/a&gt; to students/interns but retain quality). How fast can we help you make a graphic to share with your followers (and then move on with your life).&lt;/p&gt;
&lt;p&gt;Don’t move things around, it’s wasting time.&lt;br&gt;
Lock down colors, fonts and templates.&lt;br&gt;
Don’t resize logos or text.&lt;/p&gt;
&lt;p&gt;We’re different. Those differences create constraints that actually guide us to build a better product. Sure, we’ve been tempted to build drag and drop, but that would be a disservice to our customers. Their time is better spent on other things.&lt;/p&gt;
&lt;h3 id=&quot;trade-offs&quot;&gt;Trade offs&lt;/h3&gt;
&lt;p&gt;Everything is trade offs. Things like the list below would be dramatically harder or impossible if we allowed that.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://boxoutsports.com/features/multi-format-graphics-create-once-get-three-formats-automatically&quot;&gt;&lt;strong&gt;Multi-format&lt;/strong&gt;&lt;/a&gt;. Different platforms prefer different sized graphics. We handle that for you. X gets widescreen, IG 4:5 (or now 3:4), Story format. &lt;em&gt;Fill out your data once and hit share&lt;/em&gt;. Don’t duplicate and resize and move stuff around.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://boxoutsports.com/features/generate-personalized-captions-with-ai-suggestions&quot;&gt;&lt;strong&gt;Suggestions&lt;/strong&gt;&lt;/a&gt;. Not sure what to say? Hit a button and get 5 options with different tones that &lt;em&gt;smell quite similar&lt;/em&gt; to your previous shares. Of course they are based on the graphic you are attaching to the share.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-ins&lt;/strong&gt;. Need to &lt;a href=&quot;https://boxoutsports.com/features/edit-your-images-in-a-flash&quot;&gt;crop an image&lt;/a&gt; or &lt;a href=&quot;https://boxoutsports.com/features/effortlessly-edit-and-trim-videos&quot;&gt;trim a video&lt;/a&gt;? No problem. Do it right in the browser, right from the graphic you are creating. &lt;em&gt;No need to leave the browser&lt;/em&gt;. We’ll even &lt;a href=&quot;https://boxoutsports.com/features/automatically-remove-the-background-from-images&quot;&gt;remove the background&lt;/a&gt; for a stunning PNG cut out on many graphics. Not ready to share yet? &lt;a href=&quot;https://boxoutsports.com/features/planning-social-media-is-easy-with-scheduled-posts&quot;&gt;Schedule&lt;/a&gt; it for later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autofill&lt;/strong&gt;. We autofill fields for the graphic based on what you’ve previously used, &lt;a href=&quot;https://boxoutsports.com/features/sync-your-schedule-create-graphics-instantly&quot;&gt;upcoming events&lt;/a&gt;, your linked brand information, &lt;a href=&quot;https://boxoutsports.com/features/grab-any-team-logo&quot;&gt;opponents&lt;/a&gt; linked brand information, live stats, etc. Autofill means &lt;em&gt;fewer fields to fill out&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed&lt;/strong&gt;. We just spent months decreasing average graphic render time from 2.9 to 1.1 seconds. Rendering is so fast now that it feels live.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For Box Out, it’s easy to define and see the value those differences create for us (and our customers). Now it’s time to think what those differences are and will be for &lt;a href=&quot;https://fireside.fm&quot;&gt;Fireside&lt;/a&gt; and &lt;a href=&quot;https://www.flippercloud.io&quot;&gt;Flipper&lt;/a&gt;…&lt;/p&gt;
</content:encoded><category>business</category><category>thoughts</category></item><item><title>Self-Made is a Myth Podcast</title><link>https://www.johnnunemaker.com/self-made-is-a-myth-podcast/</link><guid isPermaLink="true">https://www.johnnunemaker.com/self-made-is-a-myth-podcast/</guid><description>Podcast interview where I share my journey building lasting SaaS businesses, the power of partnerships, and why I&apos;m obsessed with onboarding, risk reduction, and hiring ‘batteries included’ people.</description><pubDate>Wed, 01 Oct 2025 15:19:04 GMT</pubDate><content:encoded>&lt;p&gt;I’m never one to turn down being on a podcast, especially since acquiring &lt;a href=&quot;https://fireside.fm&quot;&gt;Fireside.fm&lt;/a&gt;, a podcast host. So yesterday, I hopped on a call with Tim Campsall to chat about running &lt;a href=&quot;https://boxoutsports.com&quot;&gt;Box Out&lt;/a&gt; and &lt;a href=&quot;https://verygoodsoftware.company&quot;&gt;Very Good&lt;/a&gt;. And the crazy thing is it’s already out on Youtube. I wasn’t in my home office so my background was bleak and my audio was subpar but still a great conversation.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/14OZttvB-24?feature=oembed&quot; title=&quot;John Nunemaker - Box Out Sports: Self Made Is A Myth Interview&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;highlights&quot;&gt;Highlights&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Shortest path between builders and users is critical.&lt;/li&gt;
&lt;li&gt;Hire “batteries included” people who are self-driven.&lt;/li&gt;
&lt;li&gt;I’m not really good at anything specific. I’m just good at being glue.&lt;/li&gt;
&lt;li&gt;Measure progress (time tracking) and celebrate wins to avoid burnout.&lt;/li&gt;
&lt;li&gt;Design products to save people time. Design your business to free your own time.&lt;/li&gt;
&lt;li&gt;People buy from people. My dream as a developer is to build a good product and never talk to anyone, but it just doesn’t work that way.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>podcast</category><category>business</category></item><item><title>Giant Robots</title><link>https://www.johnnunemaker.com/giant-robots/</link><guid isPermaLink="true">https://www.johnnunemaker.com/giant-robots/</guid><description>A few weeks back I joined Chad on his Giant Robots podcast to talk Ruby, Rails and a bit of business – including our acquisition of Fireside last year. The…</description><pubDate>Thu, 29 May 2025 14:19:23 GMT</pubDate><content:encoded>&lt;p&gt;A few weeks back I &lt;a href=&quot;https://podcast.thoughtbot.com/576&quot;&gt;joined Chad on his Giant Robots podcast&lt;/a&gt; to talk Ruby, Rails and a bit of business – including our &lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/&quot;&gt;acquisition of Fireside&lt;/a&gt; last year. The episode just went live and I hope you enjoy it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fun fact&lt;/strong&gt;: their podcast is actually hosted on &lt;a href=&quot;https://fireside.fm/&quot;&gt;Fireside&lt;/a&gt; – inception! You can listen wherever you consume podcasts or on Fireside (below) or &lt;a href=&quot;https://www.youtube.com/watch?v=URrk9eigXsI&quot;&gt;youtube&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/DiNRb69N+NgFmOaBl?theme=dark&quot; title=&quot;Embedded content&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
</content:encoded><category>podcast</category></item><item><title>Rails Business Podcast</title><link>https://www.johnnunemaker.com/rails-business-podcast/</link><guid isPermaLink="true">https://www.johnnunemaker.com/rails-business-podcast/</guid><description>I had a nice chat with Brendan and Ryan on the Rails Business podcast a few weeks ago and now its live! Search for &quot;Rails Business&quot; in your favorite podcast…</description><pubDate>Tue, 15 Apr 2025 20:28:09 GMT</pubDate><content:encoded>&lt;p&gt;I had a nice chat with Brendan and Ryan on the &lt;a href=&quot;https://www.railsbusiness.com/&quot;&gt;Rails Business podcast&lt;/a&gt; a few weeks ago and now its live! Search for “Rails Business” in your favorite podcast app or you can listen at the following link:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;bookmark&quot; href=&quot;https://www.railsbusiness.com/2435951/episodes/16978258-john-nunemaker&quot;&gt;&lt;span class=&quot;bookmark-title&quot;&gt;John Nunemaker - Rails Business&lt;/span&gt;&lt;span class=&quot;bookmark-description&quot;&gt;In this episode, Brendan and Ryan welcome John Nunemaker.&amp;amp;nbsp; John is a prominent figure in the Ruby community and, shares his journey into Ruby on Rails, his career evolution, and his unique approach to managing multiple projects simultaneously…&lt;/span&gt;&lt;span class=&quot;bookmark-domain&quot;&gt;railsbusiness.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want the tldr, we cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;my journey into Ruby and Rails&lt;/li&gt;
&lt;li&gt;my current projects and Ruby usage&lt;/li&gt;
&lt;li&gt;the role of AI in my dev process&lt;/li&gt;
&lt;li&gt;how to balance multiple projects&lt;/li&gt;
&lt;li&gt;time tracking and productivity&lt;/li&gt;
&lt;li&gt;consistency across projects&lt;/li&gt;
&lt;li&gt;the origin and success of Box Out&lt;/li&gt;
&lt;li&gt;future plans&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>podcast</category></item><item><title>Ruby on Rails Podcast: Taking over Fireside.fm</title><link>https://www.johnnunemaker.com/ruby-on-rails-podcast-taking-over-fireside-fm/</link><guid isPermaLink="true">https://www.johnnunemaker.com/ruby-on-rails-podcast-taking-over-fireside-fm/</guid><description>I was stoked when I discovered that the Ruby on Rails podcast is hosted on our platform – fireside.fm. So I reached out to Elise for feedback and to…</description><pubDate>Wed, 22 Jan 2025 21:13:43 GMT</pubDate><content:encoded>&lt;p&gt;I was stoked when I discovered that the &lt;a href=&quot;https://www.therubyonrailspodcast.com&quot;&gt;Ruby on Rails podcast&lt;/a&gt; is hosted on our platform – &lt;a href=&quot;https://fireside.fm&quot;&gt;fireside.fm&lt;/a&gt;. So I reached out to Elise for feedback and to volunteer Garrett and I for an episode.&lt;/p&gt;
&lt;p&gt;We recorded last week and its &lt;a href=&quot;https://www.therubyonrailspodcast.com/531&quot;&gt;already live today&lt;/a&gt;. Our chat covered taking over an outdated Rails app and all the progress we’ve made modernizing it the past few months. We even threw in a few stories of battle scars earned.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/3OC19MC9+qjmEkYf2?theme=dark&quot; title=&quot;Embedded content&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;P.S. It’s been &lt;a href=&quot;https://www.therubyonrailspodcast.com/289&quot;&gt;5 years since I was last on&lt;/a&gt; the rails pod (Brittany Martin was the host).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2026-10-01&lt;/strong&gt;: Two years in, almost nothing from the outdated app we took over is left. Garrett and I told the rest of the story, including Postgres 9.5 to 18 in one hop, in episode one of our new podcast, &lt;a href=&quot;https://www.johnnunemaker.com/the-friday-deploy/&quot;&gt;The Friday Deploy&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>Episode #4</title><link>https://www.johnnunemaker.com/episode-4/</link><guid isPermaLink="true">https://www.johnnunemaker.com/episode-4/</guid><description>It&apos;s out and it&apos;s stout. Actually, I don&apos;t know if it&apos;s stout or not. I just like to rhyme (all the time). My 3 Fav Quotes “What if instead of discounts, we…</description><pubDate>Thu, 09 Jan 2025 21:47:52 GMT</pubDate><content:encoded>&lt;p&gt;It’s out and it’s stout. Actually, I don’t know if it’s stout or not. I just like to rhyme (all the time).&lt;/p&gt;
&lt;h2 id=&quot;my-3-fav-quotes&quot;&gt;My 3 Fav Quotes&lt;/h2&gt;
&lt;p&gt;“What if instead of discounts, we focused on lowering the risk for customers to try podcasting?” – Garrett&lt;/p&gt;
&lt;p&gt;“You don’t have to go crazy and work a ton. You can you can achieve great success by turning a few levers. But sometimes it just takes a lot of work to figure out what those levers are.” – John&lt;/p&gt;
&lt;p&gt;“I’m just thinking about swag, but that’s a discussion from another day.” – Kris&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;bookmark&quot; href=&quot;https://blog.fireside.fm/black-friday-reflections-and-new-year-opportunities/&quot;&gt;&lt;span class=&quot;bookmark-title&quot;&gt;Black Friday Reflections and New Year Opportunities&lt;/span&gt;&lt;span class=&quot;bookmark-description&quot;&gt;I was hoping to get this out last year, but holidays got in the way of that (in a good way). So here is the last episode recorded in 2024, fresh for you to enjoy in 2025. * Black Friday Reflections and Trends * Rethinking Sales Strategies for Software * Technical Upgrades and&lt;/span&gt;&lt;span class=&quot;bookmark-domain&quot;&gt;blog.fireside.fm&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Big shoutout to &lt;a href=&quot;https://riverside.fm&quot;&gt;Riverside&lt;/a&gt;. We use them to record and edit this. And I’ve found it pretty fun the past couple times.&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>Episode #3</title><link>https://www.johnnunemaker.com/episode-3/</link><guid isPermaLink="true">https://www.johnnunemaker.com/episode-3/</guid><description>For those that haven&apos;t subscribed to the fireside blog or the podcast, I figured I&apos;d update here as well. We released episode #3 on Mastering Prioritization…</description><pubDate>Tue, 31 Dec 2024 19:33:13 GMT</pubDate><content:encoded>&lt;p&gt;For those that haven’t &lt;a href=&quot;https://blog.fireside.fm/#/portal/signup&quot;&gt;subscribed to the fireside blog&lt;/a&gt; or the &lt;a href=&quot;https://standinginthefire.fireside.fm/subscribe&quot;&gt;podcast&lt;/a&gt;, I figured I’d update here as well. We released episode #3 on &lt;a href=&quot;https://standinginthefire.fireside.fm/3&quot;&gt;Mastering Prioritization in SaaS&lt;/a&gt; last week. Give it a listen and subscribe in your favorite podcast app. At some point I’ll get too lazy to post here too. 😄&lt;/p&gt;
&lt;p&gt;One of my favorite parts was the segment on time tracking, something that I’ve found useful of late.&lt;/p&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/26YjJHTb+YBzaOy8I?theme=dark&quot; title=&quot;Embedded content&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
</content:encoded><category>podcast</category></item><item><title>Episode #2</title><link>https://www.johnnunemaker.com/episode-2/</link><guid isPermaLink="true">https://www.johnnunemaker.com/episode-2/</guid><description>Episode #1 went out last Thursday. Now here we are on Tuesday and ANOTHER EPISODE FOR YOU. I know right?! Christmas came early this year. On today&apos;s…</description><pubDate>Tue, 17 Dec 2024 13:41:23 GMT</pubDate><content:encoded>&lt;p&gt;Episode #1 went out last Thursday. Now here we are on Tuesday and &lt;strong&gt;ANOTHER EPISODE FOR YOU&lt;/strong&gt;. I know right?! Christmas came early this year.&lt;/p&gt;
&lt;p&gt;On today’s episode, we hit on a few topics:&lt;/p&gt;
&lt;p&gt;🙋 Customer feedback.&lt;br&gt;
😖 Podcasting pains.&lt;br&gt;
🆕 Future features.&lt;br&gt;
🏆 Recent wins.&lt;/p&gt;
&lt;p&gt;Just hit play… you know you want to. And then be sure to &lt;a href=&quot;https://standinginthefire.fireside.fm/subscribe&quot;&gt;subscribe&lt;/a&gt;.&lt;/p&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/26YjJHTb+k0zrWQdh?theme=dark&quot; title=&quot;Embedded content&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;In the interest of getting better, we’re improving something each episode. Today’s improvement was a wee bit of intro/outro music.&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>Episode #1</title><link>https://www.johnnunemaker.com/episode-1/</link><guid isPermaLink="true">https://www.johnnunemaker.com/episode-1/</guid><description>We did it! The Fireside crew went through the entire process of setting up a podcast and recording our first episodes. #1 is live wherever you enjoy…</description><pubDate>Thu, 12 Dec 2024 15:05:32 GMT</pubDate><content:encoded>&lt;p&gt;We did it! The &lt;a href=&quot;https://fireside.fm&quot;&gt;Fireside&lt;/a&gt; crew went through the entire process of setting up a podcast and recording our first episodes.&lt;/p&gt;
&lt;p&gt;#1 is live wherever you enjoy podcasts (probably).&lt;/p&gt;
&lt;iframe src=&quot;https://player.fireside.fm/v2/26YjJHTb+3MIL6f6q?theme=dark&quot; title=&quot;Embedded content&quot; loading=&quot;lazy&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;I never would have guessed how tedious it would be to get your first episode out the door. Now I have a ton of respect for our customers, especially our non-technical ones, who have made it through this gauntlet.&lt;/p&gt;
&lt;p&gt;So much information to fill out! I’m looking forward to getting this process locked down so new episodes will be much easier. Also, planning to start paying for an editor. 🤣&lt;/p&gt;
&lt;p&gt;We set the quality bar very low for this. We know we’ll get better with each episode but we had to start somewhere. Enjoy!&lt;/p&gt;
&lt;p&gt;And be sure to &lt;a href=&quot;https://standinginthefire.fireside.fm/subscribe&quot;&gt;subscribe&lt;/a&gt;!&lt;/p&gt;
</content:encoded><category>podcast</category></item><item><title>Shrinking a Postgres Table</title><link>https://www.johnnunemaker.com/shrinking-a-postgres-table/</link><guid isPermaLink="true">https://www.johnnunemaker.com/shrinking-a-postgres-table/</guid><description>How I used a PostgreSQL table swap to cut disk usage from 87% to 53% in about 10 seconds, with only a few seconds of possible data loss.</description><pubDate>Thu, 28 Nov 2024 14:10:17 GMT</pubDate><content:encoded>&lt;h2 id=&quot;in-short&quot;&gt;In short&lt;/h2&gt;
&lt;p&gt;I shrank a 57 GB PostgreSQL table by cloning its structure, copying only the rows worth keeping, briefly renaming the old and new tables, and then dropping the original. The swap took about 10 seconds and reduced server disk use from 87% to 53%.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identify the table and rows consuming the space.&lt;/li&gt;
&lt;li&gt;Create a replacement with &lt;code&gt;CREATE TABLE ... (LIKE ... INCLUDING ALL)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Copy only the rows you need into the replacement.&lt;/li&gt;
&lt;li&gt;Rename the old and new tables during a short maintenance window.&lt;/li&gt;
&lt;li&gt;Validate the replacement, then drop the old table to reclaim disk space.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This was a calculated tradeoff for this application. Before using the technique, verify your constraints, indexes, sequences, dependencies, write traffic, and recovery plan against your own schema.&lt;/p&gt;
&lt;p&gt;Ok folks, this is kind of a weird one. I’m going to put it in the “you won’t ever need this, but if you do, you are going to be glad I wrote this up for ya” category.&lt;/p&gt;
&lt;p&gt;As you may or may not know, I recently &lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/&quot;&gt;acquired fireside.fm&lt;/a&gt;, an awesome podcast host. While investigating a slow query, I noticed that the database servers were at 87% disk space use.&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ df -h&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Filesystem      Size  Used Avail Use% Mounted on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/dev/root       158G  129G   21G  87% /&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I typically use a managed Postgres, which makes it real obvious when you are starting to use a lot of disk space and easy to fix. But this is self-managed Postgres on Linode.&lt;/p&gt;
&lt;p&gt;Servers don’t like to run out of disk space (or even get close to running out).&lt;/p&gt;
&lt;h2 id=&quot;what-is-taking-up-the-space&quot;&gt;What is taking up the space?&lt;/h2&gt;
&lt;p&gt;So I started up a casual chat with GitHub’s Copilot. You know, the typical, “how are you?”, “oh I’m fine, you?”, “yeah, same”, “do you like long walks on the beach?”, “yeah, my database is about to fall over too”.&lt;/p&gt;
&lt;p&gt;I asked Copilot how I could quickly get the size of the database:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; pg_size_pretty(pg_database_size(current_database())) &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; database_size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D;--shiki-dark:#6A737D&quot;&gt;-- 114 GB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, my database was the problem, not some rogue log file or backup retention policy.&lt;/p&gt;
&lt;p&gt;My next question was which table is taking up all the space:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;    table_name, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;    pg_size_pretty(pg_total_relation_size(table_name)) &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; total_size&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;    information_schema&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;tables&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;    table_schema &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &apos;public&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;    pg_total_relation_size(table_name) &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;DESC&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The usual suspects filled up the top 10 (analytics/metrics):&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;            table_name&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;             |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; total_size&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;-----------------------------------+------------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; downloads&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;                         |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 57&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; GB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; downloads_archive&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;                 |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 30&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; GB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; day_downloads&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;                     |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 12&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; GB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; location_downloads&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;                |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 6235&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; metrics&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;                           |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 3537&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; user_agent_downloads&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;              |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 2145&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; spotify_day_downloads&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;             |&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; 2072&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; MB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;downloads&lt;/code&gt; seemed the largest so I started there. I wasn’t entirely sure how the table was used (again I’m new to this app). So I poked around for min and max &lt;code&gt;created_at&lt;/code&gt; times. To my surprise, there were rows going back to 2021.&lt;/p&gt;
&lt;h2 id=&quot;why-is-the-downloads-table-large&quot;&gt;Why is the downloads table large?&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;downloads&lt;/code&gt; table seemed to be a record of all the raw downloads before they are aggregated into tables more efficient for querying in a web request. As downloads are processed, they are deleted from the table.&lt;/p&gt;
&lt;p&gt;The problem was many records (10’s of thousands an hour) were not being processed and thus not being deleted. Those downloads seemed to be for episodes that no longer exist for various reasons.&lt;/p&gt;
&lt;p&gt;Over the course of many years, this added up to many 10’s of millions of rows and 35% of the disk space. I sliced and diced several queries and determined that every download older than a few hours was effectively bad data and not processable.&lt;/p&gt;
&lt;p&gt;Now I knew what my issue was, but I wasn’t sure about the best fix.&lt;/p&gt;
&lt;h2 id=&quot;how-to-shrink-the-table-with-a-table-swap&quot;&gt;How to shrink the table with a table swap&lt;/h2&gt;
&lt;p&gt;If you don’t know this already, Copilot is great for brainstorming stuff like this. Talk human to it and it’ll throw ideas back to you.&lt;/p&gt;
&lt;p&gt;Copilot really wanted me to delete the rows in batches of 1-10k and then &lt;code&gt;vacuum&lt;/code&gt; at the end. But not &lt;code&gt;vacuum full&lt;/code&gt; because that would lock the database and bring down the house.&lt;/p&gt;
&lt;p&gt;I ran the first query to delete 1k records:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;WITH&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; rows_to_delete &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;    SELECT&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;    FROM&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;    WHERE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; created_at &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &apos;2022-01-01&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;    LIMIT&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;DELETE&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; rows_to_delete);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But it took like 20 seconds.&lt;/p&gt;
&lt;p&gt;I wasn’t going to sit around and run this 30 - 50 thousand more times.&lt;/p&gt;
&lt;p&gt;I also didn’t really feel like making a background job to handle this for me.&lt;/p&gt;
&lt;p&gt;Additionally, copilot wasn’t sure how much space would actually be freed up by a &lt;code&gt;vacuum&lt;/code&gt; (as compared to a &lt;code&gt;vacuum full&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The easiest, fastest and most guaranteed way to free up space for a table is to drop it. But I did want some data out of it. That’s when I remembered table swapping.&lt;/p&gt;
&lt;p&gt;I asked Copilot for the best way to clone the downloads table:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt; downloads_new&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;LIKE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads INCLUDING ALL);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;🆒&lt;/p&gt;
&lt;p&gt;And how do I insert only the rows I need, those that are downloads for episodes that exist:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads_new &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;  SELECT&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; d.&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; FROM&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads d &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;  INNER JOIN&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; episodes e &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;token&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;episode_token&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;  WHERE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; date_trunc(&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&apos;day&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt;created_at&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &apos;2024-11-27&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;😎&lt;/p&gt;
&lt;p&gt;And lastly, how do I swap the tables:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads RENAME &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads_old;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;ALTER&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads_new RENAME &lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;TO&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sure, I could have looked these up in the Postgres docs or on Stack Overflow, but the ability to paste in your schema for your table and say in English what you want to do and get exact commands to copy is just amazing.&lt;/p&gt;
&lt;p&gt;The only bit left was to drop the original table with all the junk data:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt;DROP&lt;/span&gt;&lt;span style=&quot;color:#D73A49;--shiki-dark:#F97583&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#24292E;--shiki-dark:#E1E4E8&quot;&gt; downloads_old;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, I had a brand, spanking new &lt;code&gt;downloads&lt;/code&gt; table with only 30-40k records (past hour or so of downloads) and a whole lot more disk space:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark&quot; style=&quot;background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; df&lt;/span&gt;&lt;span style=&quot;color:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -h&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;Filesystem&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;      Size&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  Used&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; Avail&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; Use%&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; Mounted&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;--shiki-dark:#B392F0&quot;&gt;/dev/root&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;       158G&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;   80G&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;   71G&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt;  53%&lt;/span&gt;&lt;span style=&quot;color:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The best part is it took about 10 seconds to run the queries and I lost, at most, if anything, a few seconds of data during the data dump and table rename.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A worthy trade off compared to hours of coding and babysitting.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;brainstorming-with-real-people&quot;&gt;Brainstorming with Real People&lt;/h2&gt;
&lt;p&gt;Now, it’s worth mentioning that I wasn’t entirely sure if this was going to get me the result I hoped for (no downtime, low effort, and freed up space).&lt;/p&gt;
&lt;p&gt;So first, I dropped into my handy dandy, top secret slack of battle scarred programmers who are smarter than me.&lt;/p&gt;
&lt;p&gt;Akin to Copilot, I posed the same question and I got a variety of other options. I felt good about all of them, but none could compare (IMO) with the simplicity of the table swap.&lt;/p&gt;
&lt;p&gt;No one seemed overly scared that the table swap wouldn’t work. And I got a yes from two people who thought it would be easiest. That was enough to give me the confidence to try it first.&lt;/p&gt;
&lt;p&gt;Cheers to top secret slacks with smart people and AI chat bots! 🍻&lt;/p&gt;
&lt;p&gt;So that’s how I spent my Thanksgiving morning!&lt;/p&gt;
&lt;p&gt;And, honestly, I’m good with that. Feeling thankful even.&lt;/p&gt;
&lt;p&gt;I learned something new. I saved my database.&lt;/p&gt;
&lt;p&gt;And now I’m going to eat some great food and hang out with family sans a low undercurrent of stress wondering if my poor little database has crept from 87% to 88% disk usage or even higher!&lt;/p&gt;
</content:encoded><category>TIL</category></item><item><title>Founder Quest: Acquiring Fireside</title><link>https://www.johnnunemaker.com/founder-quest-acquiring-fireside/</link><guid isPermaLink="true">https://www.johnnunemaker.com/founder-quest-acquiring-fireside/</guid><description>Last, but not least for this week, I was on Founder Quest. I&apos;m doing my best third wheel impression over there and appreciate that Ben and Josh haven&apos;t…</description><pubDate>Fri, 11 Oct 2024 15:26:40 GMT</pubDate><content:encoded>&lt;p&gt;Last, but not least for this week, I was on &lt;a href=&quot;https://www.founderquestpodcast.com/episodes/acquiring-fireside-with-john-nunemaker&quot;&gt;Founder Quest&lt;/a&gt;. I’m doing my best third wheel impression over there and appreciate that Ben and Josh haven’t kicked me off yet. We talked about a lot of things but mostly focused on the &lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/&quot;&gt;fireside acquisition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;bookmark&quot; href=&quot;https://www.founderquestpodcast.com/episodes/acquiring-fireside-with-john-nunemaker&quot;&gt;&lt;span class=&quot;bookmark-title&quot;&gt;FounderQuest | Acquiring Fireside with John Nunemaker&lt;/span&gt;&lt;span class=&quot;bookmark-description&quot;&gt;Josh and Ben talk with John about his recent acquisition of Fireside, covering the finances, pitfalls avoided, and more acquisition tips.&lt;a href=&quot;https://www.johnnunemaker.com/acquiring-fireside/https://www%E2%80%A6&quot;&gt;https://www.johnnunemaker.com/acquiring-fireside/https://www…&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;bookmark-domain&quot;&gt;founderquestpodcast.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you missed the other podcasts this week, here you go:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://podcast.drbragg.dev/episodes/episode-41-john-nunemaker/&quot;&gt;Code and the Coding Coders who Code it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://changelog.com/podcast/612&quot;&gt;Changelog: The moneyball approach&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>podcast</category><category>business</category></item><item><title>The Moneyball approach</title><link>https://www.johnnunemaker.com/the-moneyball-approach/</link><guid isPermaLink="true">https://www.johnnunemaker.com/the-moneyball-approach/</guid><description>I joined Adam and Jerod to share my new thesis for acquiring Rails based SaaS apps. The conversation was great! This new moneyball approach (dubbed so by…</description><pubDate>Thu, 10 Oct 2024 18:46:49 GMT</pubDate><content:encoded>&lt;p&gt;I joined Adam and Jerod to share my new thesis for acquiring Rails based SaaS apps. The conversation was great! This new moneyball approach (dubbed so by &lt;a href=&quot;https://bjessbrown.com&quot;&gt;Jess&lt;/a&gt;) has been swimming around in my head for a few months now. So it’s great to talk about it in public finally.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://changelog.com/podcast/612&quot;&gt;Changelog Interviews 612: The Moneyball approach&lt;/a&gt; – Listen on &lt;a href=&quot;https://changelog.com/&quot;&gt;Changelog.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you like the episode, give &lt;a href=&quot;https://acquiringminds.co/articles/ryan-sullivan-north-park-group&quot;&gt;5 Businesses Acquired with a Long-Term Hold Model&lt;/a&gt; a listen too. Great stuff by someone with a lot more experience than me.&lt;/p&gt;
&lt;p&gt;If you missed the other podcasts this week, here you go:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://podcast.drbragg.dev/episodes/episode-41-john-nunemaker/&quot;&gt;Code and the Coding Coders who Code it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.founderquestpodcast.com/episodes/acquiring-fireside-with-john-nunemaker&quot;&gt;Founder Quest: Acquiring Fireside&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>