<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[SalesforceGirl]]></title><description><![CDATA[Nineteen years of Salesforce, mostly spent reading debug logs. Apex performance, untangling inherited automation, and the tools I build when the existing ones d]]></description><link>https://salesforcegirl.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6aa40b4d011a85bf7a48aa10/b894d6f3-12f4-43e2-b4c0-8c5b0773fbad.jpg</url><title>SalesforceGirl</title><link>https://salesforcegirl.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 15:39:34 GMT</lastBuildDate><atom:link href="https://salesforcegirl.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[We're on the same side]]></title><description><![CDATA[If you read my job title, you'd learn what I'm responsible for. You wouldn't learn what I actually do, or why I love doing it.
What I've really been doing my whole career is looking at how teams work.]]></description><link>https://salesforcegirl.hashnode.dev/we-re-on-the-same-side</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/we-re-on-the-same-side</guid><category><![CDATA[leadership]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Devops]]></category><category><![CDATA[agile]]></category><category><![CDATA[engineering-management]]></category><category><![CDATA[management]]></category><category><![CDATA[technical-debt]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Thu, 08 Oct 2026 18:55:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/64b4cd11-caa7-4251-8701-36878c1bc338.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you read my job title, you'd learn what I'm responsible for. You wouldn't learn what I actually do, or why I love doing it.</p>
<p>What I've really been doing my whole career is looking at how teams work. Other teams, my own team, the wider IT org, and the lines between every org in the companies I've worked at. Where does the work get stuck? Where are people doing the same thing three different ways? What's slowing them down that has nothing to do with the job they were hired to do? Where are the lines of communication failing?</p>
<p>Then I take that friction out, so they can get to the real work.</p>
<p>I love making the lives of the people around me better. At work, that looks like removing bottlenecks. At home, it looks like building an app that tells me when the water filter is due. Same instinct, different address.</p>
<h2>The work behind the work</h2>
<p>Most teams don't struggle with the work itself. They struggle with everything around it: the hand-off nobody owns, the approval that waits on one person, the manual step everyone forgot was manual, the process that made sense three reorgs ago.</p>
<p>None of it is dramatic. It's a few minutes here and an hour there. But it adds up, and it's the part that wears people out. Nobody joined a team to fight the tooling, and nobody likes a process that doesn't make sense.</p>
<p>So when I look at a team's workflow, I'm not asking "are they doing their job?" I'm asking "what's in the way of them doing it?"</p>
<h2>We're on the same side</h2>
<p>Here's the part I care about most: the whole company is one team.</p>
<p>When one team is lagging in the way it works, it doesn't stay that team's problem. It affects everyone who depends on them, and it makes every project that needs both teams harder than it has to be. You can't work well together on a shared problem if you don't share a way of working.</p>
<p>That doesn't mean every team has to work identically. Each team has its own nuances, and those are often there for good reasons. But when the foundations are shared (similar processes, similar methods, and real communication between them), nobody has to reinvent the wheel, and everyone starts on a level playing field.</p>
<p>And when something needs attention, we lean in. We help each other. We're not competing teams that happen to share a company name on our résumés. We're on the same side.</p>
<h2>From digging to watching</h2>
<p>Here's one example of what that looks like in practice.</p>
<p>Audits like SOX used to mean digging. After the fact, someone had to work out which changes were in scope, then search through tickets, release notes and deployment history to confirm when each change happened and whether it followed the controls. Half of it meant ruling things <em>out</em>, based on history nobody remembered anymore.</p>
<p>At the time, that digging fell to me. I was the only one doing the auditing, so I knew the constraints well.</p>
<p>So we flipped it. Before our team onsite, I gave the team homework: the intro courses for our integration platform, MuleSoft. Then at the onsite, I challenged them to build automation that watches for in-scope changes as they happen and flags them right away. Now the digging happens while the change is fresh, and the people who made it still remember why.</p>
<p>The win wasn't only automating a manual task. Only one person on the team knew that platform. This took away two bottlenecks at once, me as the only auditor and them as the only MuleSoft expert, and it brought the team together to solve a real problem, learn together, and grow together.</p>
<p>It's the same work. It just moved from reactive to proactive, and that one shift took a painful, backward-looking job and made it part of the everyday flow.</p>
<p>That's the pattern I keep coming back to, in every system I touch: stop finding out after the fact.</p>
<h2>I'm the cleaner</h2>
<p>I've been the cleaner of a lot of orgs and systems. I love cutting out the fat.</p>
<p>The unused fields still being filled in by some automation that does things nobody needs anymore. The three tools that each do half of one job. The workaround that became permanent because nobody had time to fix the real thing. The pile of logic on one object that sets off circles of updates behind the scenes and slows down every page load.</p>
<p>Tech debt is real. It isn't a someday list or a nice-to-have. It's the reason the simple change takes a week, the reason the new person takes a month to get up to speed, and the reason the team is tired. It slows down every project that sits on top of it.</p>
<p>A lot can be said about preventing tech debt, and honestly, even with the best processes and intentions, it will always be a byproduct of the work. Something stops being needed. Something new comes along. The vision changes. Or we just tried a thing and it didn't work the way we thought it would. When that happens, whatever was replaced needs to be removed, updated, or at the very least turned off. If it isn't, that's tech debt.</p>
<p>Left alone, it makes the foundation we build on unstable, muddied with excess. Over time it becomes a hoard that takes more and more work to dig out of. And worse, when you finally go looking for something stable underneath it all, the core pillars of logic have often been eaten away or lost. I've seen it.</p>
<p><strong>Tech debt needs a seat at the priority table</strong>, right next to the shiny new features, because it's the thing that decides how fast every one of those features gets built.</p>
<h2>The same instinct, at home</h2>
<p>This is why I build what I build on the side.</p>
<p>Saasy Logs exists because reading a Salesforce debug log shouldn't be a chore that eats your afternoon. DwelLogs exists because keeping a house running is almost always reactive: the pump quits, the filter is a year overdue, and you find out when something breaks. I wanted it to be proactive instead.</p>
<p>One of my mottos is <em>see a need, fill a need.</em> Most of the needs I see are friction: in a team, in a process, in a system, in my own laundry room. I can't help noticing it, and I can't help wanting to solve a good problem.</p>
<p>Once I've noticed it, my mind starts working. I want to understand it, and I want to make it better. For me, and for the people around me.</p>
<p>Because we're on the same side.</p>
]]></content:encoded></item><item><title><![CDATA["Add sign-in" is not one task]]></title><description><![CDATA[DwelLogs has accounts now. You sign in with a code from your email, your log follows you from phone to laptop, and it keeps working at the top of a field where the signal gives up.
On a roadmap, that']]></description><link>https://salesforcegirl.hashnode.dev/add-sign-in-is-not-one-task</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/add-sign-in-is-not-one-task</guid><category><![CDATA[Auth ]]></category><category><![CDATA[dns]]></category><category><![CDATA[email]]></category><category><![CDATA[branding]]></category><category><![CDATA[authentication]]></category><category><![CDATA[supabase]]></category><category><![CDATA[PWA]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[side project]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Mon, 05 Oct 2026 02:02:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/8afbd23b-5c39-47bc-8b12-9d3fdefbc26b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>DwelLogs has accounts now. You sign in with a code from your email, your log follows you from phone to laptop, and it keeps working at the top of a field where the signal gives up.</p>
<p>On a roadmap, that's one line: <em>add sign-in.</em> In practice it was a database, an email service, a domain's DNS records, an email template, four rounds on how signing in should work, and a whole layer for working offline. All of it on free tiers, because DwelLogs is free and I want it to stay that way.</p>
<p>Here's what's actually behind that one line.</p>
<h2>The stack, and what it costs</h2>
<ul>
<li><p><strong>Supabase</strong> for the database and sign-in.</p>
</li>
<li><p><strong>Resend</strong> to send the sign-in emails.</p>
</li>
<li><p><strong>Porkbun</strong> for the domain and its DNS.</p>
</li>
<li><p><strong>GitHub Pages</strong> for the site and the app.</p>
</li>
</ul>
<p>Every one of those is on a free tier. The domain is the only thing I pay for.</p>
<p>Free isn't the same as unlimited, though. Every free tier has a ceiling, and part of the work is knowing where each one is before you hit it.</p>
<h2>The email nobody else could get</h2>
<p>Supabase sends sign-in emails out of the box. I found out what that really means the first time I wanted someone else to try it: the built-in email only reaches people on your own project team, a few an hour. It's meant for testing. As long as DwelLogs used it, I was the only person who could sign in.</p>
<p>So DwelLogs needed its own email sender. I went with Resend: 3,000 emails a month and 100 a day free, far past what a test group sends, and it speaks plain SMTP, so Supabase only needs a few settings, not code.</p>
<p>Then comes the part nobody puts on a roadmap: <strong>DNS.</strong> For a sign-in email to land in an inbox instead of spam, the domain has to prove it's allowed to send:</p>
<ul>
<li><p>an <strong>SPF</strong> record that names who may send for the domain,</p>
</li>
<li><p>a <strong>DKIM</strong> key so receiving mail servers can check the email wasn't altered,</p>
</li>
<li><p>a <strong>DMARC</strong> record that tells receiving servers what to do when the other two checks fail (for now mine says: just report it),</p>
</li>
<li><p>and an <strong>MX</strong> record for bounces.</p>
</li>
</ul>
<p>All of it on a subdomain, <a href="http://mail.dwellogs.com">mail.dwellogs.com</a>, so sending stays separate from the address people write to. None of it is hard. All of it is fiddly, and one typo in a long DKIM key means nobody gets their code.</p>
<h2>Branding an email is like building for 2005</h2>
<p>Here's a catch I didn't expect: Supabase locks its email templates until you set up your own sender. The sign-in email couldn't even carry a code until all the DNS work was done.</p>
<p>Once it could, it had to look like DwelLogs. Email apps only read a small, old slice of HTML: tables, inline styles, no web fonts, no SVG. So the logo is a PNG the site already serves, the colours are the site's palette written out by hand, and it's dark text on a light background, because Gmail and Apple Mail darken emails on their own and that's the combination that survives it.</p>
<p>It's a small thing. It's also the first thing a new person sees from DwelLogs, before they ever see the app.</p>
<h2>A link, a code, a pasted link, then just the code</h2>
<p>This was the most surprising part, and it took four tries.</p>
<p><strong>Try one: a magic link.</strong> Tap the link in your email and you're in. Simple, until you're on a phone. On a phone, every browser and every home-screen app keeps its own separate storage. The link opens in your <em>default</em> browser, Chrome on mine, while DwelLogs lives in the app on your home screen. You'd sign in somewhere you weren't.</p>
<p><strong>Try two: a code as well as the link.</strong> You type the code into the app that's already open. Except the email template that needed to carry the code was still locked.</p>
<p><strong>Try three: paste the link.</strong> The link already carries a one-time token, so you could copy it and paste it into the app. Except on an iPhone, pressing and holding a link to copy it opens a preview, and the preview <em>uses up the link</em>.</p>
<p><strong>Try four: just the code.</strong> My own feedback, more or less word for word: just ask for the code, I don't want to do both. The app now asks for one thing: the code in the email. It works wherever DwelLogs is open. The link stays underneath, for anyone who reads email in the same browser they use the app in.</p>
<p>Each one taught me something about how phones actually behave.</p>
<h2>No signal is a requirement, not an edge case</h2>
<p>DwelLogs started at a ranch, and in rural places a signal isn't a given. The well, the barn, the back fence: none of them get a good signal. If the app stops working where the work happens, it's useless exactly when you need it.</p>
<p>So <strong>offline comes first</strong>:</p>
<ul>
<li><p><strong>A save lands on the phone first.</strong> If there's no signal, it waits in line.</p>
</li>
<li><p><strong>Waiting changes go up on their own</strong>, as soon as the phone says it's back online, and every minute while anything is waiting.</p>
</li>
<li><p><strong>A hung request gives up after 8 seconds</strong> and waits on the phone, so a flicker of service never freezes the screen.</p>
</li>
<li><p><strong>Home tells you how many changes are waiting</strong>, so nothing is a mystery.</p>
</li>
<li><p><strong>Only the fields you changed are sent</strong>, so two people editing different parts of the same job don't overwrite each other.</p>
</li>
</ul>
<p>There's one more catch: an iPhone clears a website's saved data after about a week of not being used, unless it's been added to the home screen. So the app now walks you through adding it, step by step for iPhone Safari, iPhone Chrome, and Android.</p>
<h2>Say only what works today</h2>
<p>The last step wasn't code. When sign-in changed how DwelLogs stores your data, some features on the site, like sharing through a Google Sheet, reminders, and invites, were no longer something a new person could actually use. So they came off the site until they were back for real. Invites are already back, in account terms; reminders come back when they work with accounts too. The homepage says what the app does <em>today</em>, not what it will do someday.</p>
<h2>The unglamorous majority</h2>
<p>When people picture building an app, they picture screens. Most of the work is the stuff underneath: DNS records, email templates, how a phone shares storage, what happens when the signal drops halfway through a save.</p>
<p>That's the work that decides whether someone can actually use the thing. Nobody notices it when it's right. Everybody notices when their sign-in code never arrives.</p>
<p>DwelLogs has accounts now, and it keeps working when the signal doesn't. It took a lot more than one line on a roadmap.</p>
]]></content:encoded></item><item><title><![CDATA[Real data is messy. Build the model first.]]></title><description><![CDATA[Until this year, every database I'd ever worked in professionally had Salesforce wrapped around it.
That's not a confession, exactly. I've been building on Salesforce since 2007: always in IT, always ]]></description><link>https://salesforcegirl.hashnode.dev/real-data-is-messy-build-the-model-first</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/real-data-is-messy-build-the-model-first</guid><category><![CDATA[supabase]]></category><category><![CDATA[Salesforce]]></category><category><![CDATA[data-modeling]]></category><category><![CDATA[database]]></category><category><![CDATA[AI]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Fri, 02 Oct 2026 06:20:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/31bcd285-06eb-40d0-abf3-84f668e5d91f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Until this year, every database I'd ever worked in professionally had Salesforce wrapped around it.</p>
<p>That's not a confession, exactly. I've been building on Salesforce since 2007: always in IT, always finding myself fixing, improving and hunting for a cleaner way to do things. Nineteen years of real applications inside a CRM.</p>
<p>I never went to college. I dropped out after a few months; I'd never wanted to go in the first place. I wanted to make things with my hands: metal sculpture, design, photography, woodworking. I wanted to change the world somehow through people's experience, using my own.</p>
<p>So I taught myself, and kept going. From nineteen until a few years ago I read many books, especially the O'Reilly <em>Head First</em> books nonstop (I own nearly all of them), along with object-oriented programming, <a href="http://ASP.NET">ASP.NET</a>, and lately chemistry, for no reason other than wanting to know. The hands-on dreams didn't go anywhere either: creating things, fixing, and these days a 442 in the garage. All self-taught, all for the joy of learning something and then using it somewhere else.</p>
<p>But a CRM's query language is a like a kids playground compared to a real one. You query along the relationships the platform lets you define, inside the limits it sets, and you learn to design around what you <em>can't</em> ask. That turned out to be excellent training. When you can't paper over a bad structure with a clever query, you learn to get the structure right.</p>
<p>So when DwelLogs needed a real database, I didn't start with the database. I started with the model.</p>
<h2><strong>The model comes first</strong></h2>
<p>My whole career, I've watched bad data make or break the application built on top of it. Not only bad input, the typo, the blank field, the "misc" category that ends up holding half the records, but bad <em>structure</em>. An object that tries to be three things. A relationship that should have been a lookup and became a text field. A shortcut taken in week one that every screen after it has to work around.</p>
<p>You can redesign a page in an afternoon. Changing the shape of the data underneath a live app is a migration, and it touches everything.</p>
<p>So before there were screens, there was an object model, and I worked on it until it was right. DevOps, Agile, years of watching what users actually do versus what we assumed they'd do: all of it pointed the same way. Get the foundation right, then build the pages that serve it.</p>
<p>I had a head start most product teams don't: I'm the user. I knew how I wanted to sort my own data. I knew what would make my own life easier, at a ranch with a propane tank at the top of a field, three fridges, and a drawer full of manuals that never say <em>when</em>. And I asked the people around me what they'd actually use an app like this for, because one user's habits aren't a product.</p>
<p>The goal was never "track everything." It was to take something that's usually reactive (the well pump quits, the filter's a year overdue, the dryer works <em>MOST</em> the time) and make it proactive. Easy to reach for. Quick to log. Telling you what's coming before it arrives.</p>
<h2><strong>Narrow is a feature</strong></h2>
<p>In a world of possible, everything looks like a feature. Calendar sync! Photo uploads! Sharing! Smart suggestions! Every one of them is a good idea, and building them all at once is how you end up with a bunch of half-baked ideas and no product.</p>
<p>So the first version has a line, and the line is the data, not the feature list. Get one person's real house into the model, make it fast and pleasant to use, and let the rest wait until the foundation can carry it. Photo uploads were actually built, and then pulled back out, because holding other people's files is a promise, and that promise waits until there are accounts to make it to.</p>
<h2><strong>Start with a spreadsheet, on purpose</strong></h2>
<p>The first DwelLogs storage was a Google Sheet. Not because a spreadsheet is a good database (it isn't) but because it's an excellent place to find out <em>where your model is wrong</em>. You can see every row at once and fix a hundred of them in ten seconds.</p>
<p>It was a test bed, built to be thrown away happily. And it taught me exactly what I needed to know:</p>
<ul>
<li><p><strong>Which relationships hurt.</strong> Type a thing's name slightly wrong in a column that's supposed to point at another table, and you feel referential integrity instead of reading about it.</p>
</li>
<li><p><strong>Which fields nobody fills in.</strong> A field that's always blank after a few weeks of real use is a field to cut. No design meeting settles that argument faster.</p>
</li>
<li><p><strong>What a spreadsheet can never do.</strong> I had a setting that hid costs from someone you'd invited. It hid them <em>on their screen</em>. Anyone with the sheet link could still read every number. That's a UI convention dressed up as a permission, and only a real backend can turn it into a real one.</p>
</li>
</ul>
<h2><strong>Choosing the database: evidence over comparison charts</strong></h2>
<p>By the time I sat down to choose, I wasn't choosing from a feature table. I was choosing against things I'd learned from real data.</p>
<ul>
<li><p><strong>Firebase</strong> was out on a fact, not a preference. A new free project can't get file storage without a card on file, and a free app shouldn't need one.</p>
</li>
<li><p><strong>MongoDB</strong> was out on shape. A document store is the right tool for documents, and this isn't one. DwelLogs is relationships all the way down, and the questions I want to ask of it are plain SQL.</p>
</li>
<li><p><strong>AWS's free tier</strong> expires after a trial. A free app can't live on a trial.</p>
</li>
<li><p><strong>Supabase</strong> won: Postgres, sign-in built in, and row-level security, which is exactly the thing the spreadsheet could never do.</p>
</li>
<li><p><strong>Neon</strong> was a close second, and better on two counts: it wakes itself up where Supabase's free tier pauses after a week of quiet, and it keeps backups where Supabase's free tier keeps none.</p>
</li>
</ul>
<p>Here's the part that actually decided it: <strong>both are Postgres.</strong> If either limitation ever bites, moving is a dump and a restore, not a rewrite. The best reason to pick a database isn't that it's the best. It's that the way out is cheap.</p>
<h2><strong>Sign-in isn't about keeping people out</strong></h2>
<p>This week I'm wiring up sign-in, and the framing that made it click was this: authentication is mostly about knowing <em>who someone is</em>, not about locking a door.</p>
<p>In the order you actually need it:</p>
<ol>
<li><p>The same log on your phone and your laptop.</p>
</li>
<li><p>Jared logging as Jared, on his own phone.</p>
</li>
<li><p>Permissions that are enforced by the server, not just hidden on a screen.</p>
</li>
<li><p>Getting back in when you lose your phone.</p>
</li>
</ol>
<p>Only the last one is really about security. The first three are about identity. And because it's an email link, nobody has to invent a password for a house maintenance app.</p>
<h2><strong>Balance is the whole job</strong></h2>
<p>Speed matters too. Every layer of cleverness in a model is a layer the app has to walk through before it can show you anything. Too simple and the model can't grow; too complex and it's slow and fragile. The craft is keeping it simple enough to make sense and flexible exactly where it counts.</p>
<p>That balance is the key to real change in applications, and it's the same thing holding most organizations back from AI. The tools are ready. The data usually isn't.</p>
<h2><strong>AI will build on whatever you hand it</strong></h2>
<p>Here's the funny part. Anyone can spit out an app with AI now. But an app built without understanding this crumbles fast, because the back end was designed by the same thing that's going to consume it and write code on top of it. If nobody who understands data shaped the model, the AI didn't either. It made something that <em>looked</em> right.</p>
<p>Real data is messy. How we collect it is messier still. And organizing data tells a story, whatever story you want. That's what happens with data collected by others: they pull out the story that serves their purpose and play it back with their own bias.</p>
<p>Keeping bias, false confidence and defensiveness out of an AI-assisted build is just as hard. AI is only as good as the context it's working in.</p>
<p>And that context is the data you. give. it.</p>
]]></content:encoded></item><item><title><![CDATA[AI is on the utility belt. It isn't Batman.]]></title><description><![CDATA[The first draft of my last blog post said my house came with no manuals. There's a drawer full of them in my kitchen in my laundry room.
The sentence was clean, confident, and wrong. AI helped me writ]]></description><link>https://salesforcegirl.hashnode.dev/ai-is-on-the-utility-belt-it-isn-t-batman</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/ai-is-on-the-utility-belt-it-isn-t-batman</guid><category><![CDATA[leadership]]></category><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[tech leadership]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[engineering-management]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Tue, 29 Sep 2026 16:48:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/f1390b70-9050-4861-89d5-7f132689037c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The first draft of my last blog post said my house came with no manuals. There's a drawer full of them <s>in my kitchen</s> in my laundry room.</p>
<p>The sentence was clean, confident, and wrong. AI helped me write that draft, and it did exactly what it's good at: it took what it had and made it read well. What it couldn't do was open the drawer. Only the person who lives here could catch that.</p>
<p>That's this whole post in one example.</p>
<h2>I'm not anti-AI. I use it every day.</h2>
<p>Let me be clear about where I stand, because this isn't a "robots bad" post. I build my side projects, SaasyLogs and DwelLogs, with AI as a daily working partner. It drafts, it researches, it writes the first pass of the thing I'd otherwise type twice. One of my mottos is <em>work smarter, not harder</em>, and AI is one of the smartest tools I've ever had.</p>
<p>But it's a tool. It lives on the utility belt, next to the grappling hook and the smoke pellets. Batman is the one who decides which one to reach for, when, and what the mission actually is.</p>
<h2>What only the human brings</h2>
<p>Here's what I keep running into, building real things with a very capable tool.</p>
<ul>
<li><p><strong>Context.</strong> AI knows what's <em>typical</em>. You know what's <em>true</em>. It knows most houses come with manuals, or don't. It doesn't know about my drawer, or that the ADU runs on its own holding tank, or that one of my three fridges already moved out to <s>the barn</s> the ADU. The more specific the truth, the more it has to come from a person.</p>
</li>
<li><p><strong>Taste.</strong> The SaasyLogs logo is an S and L wearing sunglasses. We went through round after round on where the glasses should sit. At one point the design moved them up, and my feedback was simply: <em>"no I do not like the sunglasses that high."</em> No amount of reasoning gets you to that. Somebody has to look at it and know. We also learned to judge designs at full size. A call made from a tiny thumbnail preview nearly threw out the version we ended up shipping. It looked broken small and was fine at real size. Now the rule is written down: judge it at 1:1, with your own eyes.</p>
</li>
<li><p><strong>Judgment.</strong> When a copycat app showed up with a name close to DwelLogs, AI gave me a thorough rundown of trademark options. Good information. But deciding that roughly $1,000 wasn't worth spending right now, on a free app with no revenue, was my call. The tool can lay out the options. It can't own the tradeoff.</p>
</li>
<li><p><strong>Accountability.</strong> I have a rule in all my projects: <em>never invent a number, and check how the number was produced.</em> It's there because the failure I've seen most often isn't bad code. It's a confident figure in a summary that doesn't hold up once somebody checks how it was calculated. AI will confidently give you a number. A person has to be the one who checks it, because a person is the one who signs their name to it.</p>
</li>
</ul>
<h2>Leading with AI is still leading</h2>
<p>Here's the part that surprised me: working well with AI uses exactly the skills I use leading engineering teams.</p>
<p>I keep a file at the top of my projects folder called "How we work." It says whose machine this is, what never goes into a public repo, how we branch, how we version, what accessibility means for us, and how I want feedback. It exists because context dies at the end of every chat, and re-explaining it every time is a tax.</p>
<p>Read it again and it's an onboarding doc. It's the same thing I'd hand a new engineer on day one.</p>
<ul>
<li><p><strong>Clear context:</strong> what we're building, and why.</p>
</li>
<li><p><strong>Standards:</strong> what "done" looks like, written down, not assumed.</p>
</li>
<li><p><strong>Review:</strong> nothing ships because it looks right. It ships because someone checked.</p>
</li>
<li><p><strong>Permission to push back:</strong> one of my written rules is <em>"Push back when something is wrong. Being agreeable about a bad number is worse than being blunt about it."</em> I wrote that for the AI. It's also exactly what I ask of the people on my team.</p>
</li>
</ul>
<p>The skills didn't change. The new team member did.</p>
<h2>For the people we lead</h2>
<p>This is the part I care about most as a manager.</p>
<p><strong>AI should take the drudgery out of the work, not the people.</strong> The best use of AI on a team is removing the toil nobody wanted: the boilerplate, the status summaries, the fourth reformat of the same data. If that frees your team up for the hard, human problems, that's a win. If it's quietly used to make people feel replaceable, you'll lose the people you most need to keep.</p>
<p><strong>Juniors still have to learn why.</strong> AI can hand a new engineer a working answer. It can't hand them the understanding they'd have built by getting there. As leaders, we have to protect the learning part. Pair on it. Ask <em>why does this work?</em> Review the reasoning, not just the output.</p>
<p><strong>Team health matters more now, not less.</strong> People are watching how their leaders talk about AI. They can tell whether you see it as something that helps them or something that replaces them. That trust is the job, and no tool on the belt does it for you.</p>
<h2>The belt is full. You still choose.</h2>
<p>Work smarter, not harder. I believe that more than ever.</p>
<p>But smarter includes knowing when the tool is wrong. It includes opening the drawer, looking at the logo at full size, checking the number, and making the call. AI is the best thing I've added to my toolbelt in years.</p>
<p>It still isn't Batman. We are.</p>
]]></content:encoded></item><item><title><![CDATA[See a need, fill a need: why I'm building DwelLogs]]></title><description><![CDATA[This year I bought my first house. It came with a well, a septic system, a saltwater pool, a propane tank, kerosene heat, and three fridges. It also came with a drawer full of manuals.
Great, I though]]></description><link>https://salesforcegirl.hashnode.dev/see-a-need-fill-a-need-why-i-m-building-dwellogs</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/see-a-need-fill-a-need-why-i-m-building-dwellogs</guid><category><![CDATA[maintenance]]></category><category><![CDATA[technology]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[side project]]></category><category><![CDATA[Build In Public]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Sun, 27 Sep 2026 17:48:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/f11ff2a4-ebaa-42b6-9c5c-f542ee710bde.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This year I bought my first house. It came with a well, a septic system, a saltwater pool, a propane tank, kerosene heat, and three fridges. It also came with a drawer full of manuals.</p>
<p>Great, I thought. Then I opened them. Every one tells you how to install the thing and what the warranty covers. None of them tell you when to do anything, or how to figure out what's wrong when it starts making a new noise. There's no schedule and no troubleshooting. Nothing says "check this before you call someone."</p>
<p>I've spent almost twenty years building systems that tell teams what's due, who owns it, and what it'll cost. Yet there I was, digging through that drawer, trying to work out when the water softener needed salt and how often a septic tank gets pumped. Did you know a tankless water heater needs flushing every year? I didn't. Most first-time owners don't. You find out when something breaks.</p>
<p>So: see a need, fill a need. Then my family wanted it too Around the same time, my brother-in-law pitched almost the same idea. He lives in a regular house in a regular neighborhood: no well, no septic, no propane. He still had the same problem. Filters, gutters, smoke detector batteries, the furnace guy's number: it all lives in scattered notes, old receipts, and memory.</p>
<p>That gave me my test. If one model handles a ranch and a suburban house, it's general enough for almost anyone. That includes condos, where the HOA owns the outside, and renters, where the landlord is just another contact. A week later, you can open it This moved faster than I expected. There's now a walkthrough of the whole thing at dwellogs.com/see, and none of it is a mock-up: every screen is the app.</p>
<p>Here's how it goes.</p>
<p>You start by pointing at your place. A house, a ranch, a farm, a cabin, a tiny house, a boat, or a patch of land with nothing on it yet. What you pick changes what you get asked later. A boat is never asked about a basement.</p>
<p>Then you fill in as much or as little as you like. There's no wizard. Every section is a tile you can open in any order, and "not set" is a state, not a failure. If you want to skip everything and go straight to the broken dryer, do that.</p>
<p>It asks what your place runs on. Well or city water, septic or sewer, wood, propane, or kerosene. One house often runs all three. Each answer brings its own check-ups with it. "Not sure yet" is a real answer, and nothing you haven't answered will ever chase you about it.</p>
<p>It knows where you are, roughly. The climate is guessed from your region and corrected by you. Where the house sits is a separate question. Two houses in the same county need different work if one is on a valley floor that frosts and the other is under trees that fill the gutters.</p>
<p>It keeps a list of what needs doing. Nobody sets up a home app mid-leak. You do it on a calm morning with three or four jobs already in your head. A job and a fault get filed separately, and "it works sometimes" is its own answer, because the thing that fails on Tuesday and behaves on Wednesday never quite earns the call.</p>
<p>Then it has a pulse. The line across the top is drawn from your own things: one shape per thing you track, with its height showing how close that thing is to needing you. A well gets a pump curve, a septic tank a square wave, and anything that burns gets a flame spike. Two places never draw the same line.</p>
<p>It only speaks when you ask. Reminders are off by default. Choose an email digest or a feed your calendar reads, and set a cap it won't go past. An empty digest is never sent.</p>
<p>And it isn't all in one person's head. Invite somebody and they get a link that carries everything. One tap and they're in, and they can see what's due and mark it done. Costs are off by default and on their own switch, because somebody helping with the list doesn't need to know what the roof quote came in at. What I've learned building it This is where the Salesforce brain kicked in. Some of these surprised me.</p>
<ol>
<li><p>Not everything is "every N months." Every to-do app assumes a schedule is a calendar interval. That's true for air filters, but softener salt runs out at a rate: one bag every two weeks, and you want five on hand. Propane is neither. You check the level, and when it crosses a line, you order a fill. So DwelLogs has three kinds of schedules: time-based, consumption-based, and level-based. Squeezing salt and propane into "every N months" would mean the app lies to you.</p>
</li>
<li><p>Every interval says where it came from. This is my answer to the drawer. A check-up in DwelLogs tells you whether its timing comes from the manual, from code, or from our best estimate. You can trust it at the level it deserves, and change it when you know better.</p>
</li>
<li><p>Three fridges is an ordinary number of fridges. Salesforce folks will recognize this one. A fridge type carries the default check-ups, and each real fridge is its own record with its own filter part number. You enter counts, not checkboxes, because one row for all three would lose two of them.</p>
</li>
<li><p>Silence is a correct output. The easiest way to make an app nobody opens is to have it nag. DwelLogs doesn't remind you about something you haven't told it, and if you moved in during June, it won't ask about winterizing you can't judge yet. A calm pulse line is a true reading, not a reward.</p>
</li>
<li><p>Words matter. They're check-ups, not chores. Status is healthy, due soon, or needs attention, never "overdue" or "failed." There's no "honey-do." The app is for anyone who holds the keys, whether they live alone or share the house.</p>
</li>
<li><p>Draw the v1 line by building, not by arguing. I designed a lot of the data model up front: 36 tables, covering animals, warranties, budgets, emergency plans, and how buildings connect to each other. Then I built the first-run flow, from an empty screen to something worth opening tomorrow. That path touched nine tables. Add what makes it worth keeping past week one, and v1 is sixteen. The other twenty are real and designed, and they wait.</p>
</li>
<li><p>Your data should live where you can see it. Right now, DwelLogs saves to your device by default, and nothing leaves it. If you want it on a second device, or want to share it, your log lives in a Google Sheet you own, with a small Apps Script in front of it. There's no account. And if you ever want out, you already have the whole thing in a spreadsheet.</p>
</li>
</ol>
<p>That setup is a test harness, built to put a real year of a real house through the model and find where it hurts. It will be replaced. But it taught me one Apps Script lesson worth passing on: if a static site calls your web app, deploy it as Execute as: Me. "User accessing the web app" sounds safer, but the browser gets a sign-in redirect instead of an answer, and fetch fails with what looks like a CORS error. It isn't one. Where it's at DwelLogs is an early test. The app is at dwellogs.com/app, and you can try it on your own device with nothing leaving it. Things will move, and I want to hear what breaks.</p>
<p>If you've ever googled "how often do you pump a septic tank" at 11pm, this one's for you.</p>
<p>See a need, fill a need.</p>
]]></content:encoded></item><item><title><![CDATA[Logs record events, not silence]]></title><description><![CDATA[Here are two consecutive lines from a production debug log. Nothing between them. No line was deleted, no section trimmed.
13:29:15.191 (1878656913)|SOQL_EXECUTE_END|[358]|Rows:1
13:29:26.282 (1228292]]></description><link>https://salesforcegirl.hashnode.dev/logs-record-events-not-silence</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/logs-record-events-not-silence</guid><category><![CDATA[Salesforce]]></category><category><![CDATA[salesforce development]]></category><category><![CDATA[debugging]]></category><category><![CDATA[saas development ]]></category><category><![CDATA[Salesforce Developer]]></category><category><![CDATA[Apex]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Mon, 21 Sep 2026 05:27:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/967e0cf9-0c03-4c20-bd31-6500154a67b0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here are two consecutive lines from a production debug log. Nothing between them. No line was deleted, no section trimmed.</p>
<pre><code class="language-plaintext">13:29:15.191 (1878656913)|SOQL_EXECUTE_END|[358]|Rows:1
13:29:26.282 (12282920584)|DML_BEGIN|[357]|Op:Update|Type:SObject|Rows:4
</code></pre>
<p>Look at the clock. 15.191 and then 26.282.</p>
<p>Eleven seconds. Between two lines that sit right next to each other in the file.</p>
<p>Ten point four of those seconds are unaccounted for, and they are sixty percent of everything that transaction logged.</p>
<p>Nobody had ever looked at it. Not because anyone was careless — because there was nothing there to look at.</p>
<h2>A quick note on which number to trust</h2>
<p>Those two lines carry two different clocks, and they disagree.</p>
<p>The wall clock says 11.091 seconds. The nanosecond counter in brackets says 10.404. They are 687 milliseconds apart, in the same file, describing the same gap.</p>
<p>I use the nanosecond counter, because that is the one Salesforce actually measures elapsed time with; the wall clock is stamped per line and drifts. But the honest answer is that I picked one and told you which. Telling you which one I picked is the least I can do, and it runs through the rest of this.</p>
<h2>The expensive part is often the gap</h2>
<p>This is the thing I keep coming back to. A debug log is a list of things that happened. Every line is an event: a query ran, a method started, a DML statement fired. The tooling we all use reads that list and shows it to you, prettier.</p>
<p>But the expensive thing in a slow transaction is very often not an event. It's the absence of one. It's the time between two events that nothing accounts for.</p>
<p>And a list of events has no row for "and then eleven seconds passed."</p>
<p>So when you open a 25 MB log looking for what made your save slow, every tool you have — including the raw file, including the Developer Console, including the good open-source flame chart extensions — shows you the things that are there. The gap is rendered as exactly what it looks like: two adjacent lines. You scroll past it, because it's not shaped like a problem.</p>
<p>I scrolled past that particular gap for a long time.</p>
<h2>I come in as the cleaner</h2>
<p>I've been building on Salesforce since 2007. LogMeIn first, where I was one of the only people who touched the Apex, then Facebook, then a few years at Salesforce itself, and now managing a systems engineering team at SurveyMonkey.</p>
<p>Almost none of that has been the shiny new thing. I come in as the cleaner.</p>
<p>The org has been hoarded. The business kept adding and nobody ever prioritized removing, so there are hacks on hacks and code that should never have passed review — usually not because anyone was bad at their job, but because there was pressure to ship a thing, or because they genuinely didn't know better yet. Then those people moved on, or the company did, and what's left is mounds of automation nobody living can account for.</p>
<p>This is not a small-company problem either. Even at the mothership there were years of things that did a job once and were never turned off, layered into the clutter, on an org too heavily built on to migrate away from. Teams needed it. It didn't work well. Rebuilding cost more than enduring. So it stayed.</p>
<p>Change avoidance is real, everywhere, and it isn't stupid: the evil you know is safer than the evil you don't.</p>
<p>The consistent thing across all of it is not that the code is bad. It's that <strong>nobody can see what's actually in play any more.</strong> You can see the errors, sure. Errors are easy — something broke and said so. What I wanted was to watch a save happen and see <em>the whole route</em>: which trigger fired, what it called, which flow woke up, which workflow rule fired on the way past, what each of them touched. Not what the code says can happen. What did happen, this time, in order.</p>
<p>Because you cannot cut the fat if you can't see it. You end up guessing at what's safe to remove, which is how things never get removed.</p>
<p>And if you've done this work you know the feeling. Something is slow. You turn logging up to FINEST. You get back a 25 MB text file with 168,000 lines in it, and roughly 400 of them matter, and you have no idea which 400.</p>
<p>I got tired of that. So around ten years in, I started building something that wouldn't just tell me, but show me. I wanted to see it visually.</p>
<h2>Four times</h2>
<p>I've built this tool four times now.</p>
<p><strong>The first</strong> was an Apps Script I wrote from scratch. It took months and it paid off — it did the thing I actually needed, which at the time was enough. I lost it. Not deprecated, not replaced: lost. It is simply gone, and everything since has been partly an attempt to get back to where it already was.</p>
<p><strong>The second</strong> was Apex, in the org — a custom object, attach a log file to it, a trigger parses the body. I got the plumbing working and then life happened. That code still exists in a folder on my laptop, with the parser half-written and the next step commented out at the bottom.</p>
<p><strong>The third</strong> was another Apps Script, about a year ago. It worked, in the sense that it produced output. It was also wrong in ways I didn't find until I went looking, which I'll come back to. It was a stepping stone, and I didn't know that at the time — you rarely do.</p>
<p><strong>The fourth</strong> is the current one, and it exists because AI made another attempt survivable. Not because it wrote the code — because it made the tedious parts fast enough that I could keep my attention on the parts that actually needed thinking about. That's a real difference, and I don't think we talk about it honestly enough.</p>
<h2>What the last one got wrong</h2>
<p>Worth being specific here, because it's the whole reason I care about this so much.</p>
<p>My own tool — the one I wrote, the one I trusted — had a bug where it never handled <code>FATAL_ERROR</code> at all. One of my sample logs contained four of them. The actual reason that transaction died, <code>System.LimitException: Apex CPU time limit exceeded</code>, did not appear anywhere in the output. The tool read the log, produced a nice tidy report, and silently omitted the cause of death.</p>
<p>It got worse. It had a pattern for the marker Salesforce inserts when it discards part of a log, and the pattern was wrong — it looked for four asterisks where Salesforce writes three. So a log that was missing 35.8 MB of content came back reported as complete, with confident-looking timings computed from data that wasn't there.</p>
<p>That's the failure mode that scares me. Not a tool that breaks. A tool that's quietly, plausibly wrong, and hands you a number you'll repeat in a meeting.</p>
<p>So the current version has a rule: <strong>never invent a number.</strong> If a duration wasn't measured, don't display one. If Salesforce threw away part of the log, say so before saying anything else. If the same work ran twice and the clock disagrees, report the spread rather than the average and let the reader decide whether to trust it.</p>
<h2>What it says now</h2>
<p>Fed the same log, the current version opens with this:</p>
<blockquote>
<p>10.40 s — 60% of the whole transaction — is unlogged time, between <code>SOQL_EXECUTE_END</code> and <code>DML_BEGIN</code>.</p>
<p>Overall, 96% of the elapsed time has no log line explaining it.</p>
<p>2 updates cost 5.13 s across 5 rows; the slowest single one took 4.63 s. That span includes every trigger, flow and validation the save set off — not just the write.</p>
</blockquote>
<p>That last line matters more than it looks. A <code>DML_BEGIN</code> to <code>DML_END</code> span isn't the write. It's the write plus every trigger, flow, workflow and validation rule the write woke up. So "saving Accounts is slow" is almost never the finding. The finding is what the save set off.</p>
<p>Ninety-six percent unaccounted, incidentally, is not unusual. It's what a log looks like when most of the real cost is happening somewhere the log doesn't narrate.</p>
<h2>And then it caught me</h2>
<p>I wrote a draft of this post that said "that transaction took 17.3 seconds end to end."</p>
<p>It didn't. Or rather: I don't know that it did, and neither does the log.</p>
<p>A later version of the tool learned to check whether a log actually records the boundaries of its own transaction — the <code>EXECUTION_STARTED</code> and <code>EXECUTION_FINISHED</code> markers. This one records neither. It begins mid-transaction and stops before the end. So 17.3 seconds is the distance between the first and last lines that got written, which is not the same thing as how long the work took, and the difference is unknowable from this file.</p>
<p>I assumed that was a quirk of one unlucky log. Of the nineteen sitting on my machine, nine record both markers and ten record neither — including both of the largest, at 143,685 lines each.</p>
<p>Those nineteen are not a sample of anything, and I want to be careful about that, because it is exactly the kind of number this post is complaining about. They are the ones I pulled out of hundreds because they were slow, or enormous, or had already gone wrong. Nobody keeps the boring ones.</p>
<p>But that is also the only kind of log anybody opens on purpose. So the useful version of the finding is narrower and worse: <strong>among the logs you would actually bother to investigate, a good half cannot tell you where their own transaction started or stopped</strong> — and nothing on the face of one tells you which kind you're holding.</p>
<p>Run it through today and the tool says so itself:</p>
<blockquote>
<p>The log does not record where this transaction ended. Neither the start nor the end of this transaction is recorded here, so 16.64 s of unlogged time and the span it is measured against describe the lines that were written, not necessarily the whole run.</p>
</blockquote>
<p>I had written a post about tools that hand you confident numbers, using a confident number I had no business being confident about. The tool caught it. That is the most reassuring thing that has happened to this project.</p>
<h2>The part that generalises</h2>
<p>I don't think this is a Salesforce problem. I think it's a logging problem.</p>
<p>Almost every log format is a list of events, and almost every log tool is a better list. That's useful. But the interesting question is usually not "what happened" — it's "where did the time go," and those are different questions with different answers.</p>
<p>If you build or use log tooling of any kind, it's worth asking what yours does with silence. Does it show you a gap? Does it rank gaps? Does it tell you when it can't see the edges of what it's measuring? Or does it faithfully render two adjacent lines and leave you to notice the timestamps yourself?</p>
<p>Mine didn't, for years. Now it does, and it's the first thing it tells me.</p>
<h2>It's free</h2>
<p>The tool is called Saasy Logs. Paste a Salesforce Apex debug log into a Google Sheet and you get the route back: every trigger, flow, workflow rule, validation and class it hit, in the order it hit them, with a ranked diagnosis instead of a data dump.</p>
<p>It's free. Not free-for-now, not a trial, not a demo with the good part behind a wall — I built it because I needed it, and it costs me nothing to let you have it too.</p>
<p>It asks for no Google Drive permission at all. It can only see the spreadsheet you opened it from, there's no server behind it, and nothing is stored anywhere once the run finishes.</p>
<p><a href="https://saasylogs.com">saasylogs.com</a></p>
<p>If you've got a log that breaks it, I'd honestly love to see it. That's how the last three bugs got found.</p>
]]></content:encoded></item><item><title><![CDATA[I shouldn't have to debug my debugger]]></title><description><![CDATA[If you grabbed your coffee on September 1st and logged into Salesforce expecting the trusty Developer Console you've relied on for years, you were probably in for a rude awakening.
Winter '27 landed, ]]></description><link>https://salesforcegirl.hashnode.dev/i-shouldn-t-have-to-debug-my-debugger</link><guid isPermaLink="true">https://salesforcegirl.hashnode.dev/i-shouldn-t-have-to-debug-my-debugger</guid><category><![CDATA[Salesforce]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[Apex]]></category><category><![CDATA[salesforce development]]></category><category><![CDATA[Salesforce Developer]]></category><category><![CDATA[debugging]]></category><dc:creator><![CDATA[Randi W]]></dc:creator><pubDate>Fri, 11 Sep 2026 18:01:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/bfc53a32-551b-443f-92df-5219f7bc4e0f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you grabbed your coffee on September 1st and logged into Salesforce expecting the trusty Developer Console you've relied on for years, you were probably in for a rude awakening.</p>
<p>Winter '27 landed, and your daily driver got swapped out for the new Salesforce Web Console — a browser-native IDE built on the VS Code engine.</p>
<p>If there's one absolute constant in tech, it's change. Having spent more years in this ecosystem than I'd care to admit, I've learned that spending bandwidth complaining about lost muscle memory won't ship releases, and nostalgia won't pass a build. Pointing fingers and fighting the tide gets you nowhere. The quicker you pivot, adapt and master the new layout, the better.</p>
<p>So instead of grumbling, I went hunting that morning for my daily bread and butter: Apex code coverage.</p>
<p>Below are the eight steps to find it, with screenshots. Then, further down, what happened when I actually tried to live in this thing for a week.</p>
<hr />
<h2>First, why coverage even matters</h2>
<p>This isn't about scraping past the arbitrary 75% threshold to force a deployment through a pipeline.</p>
<blockquote>
<p>Too often, PRs include padded test classes that boost overall numbers without actually validating the lines of code being modified.</p>
</blockquote>
<p>That's the part worth caring about. Coverage is only useful if it tells you what your functional tests are actually touching. A class sitting at 90% because someone wrote a test that instantiates it and asserts nothing is worse than a class at 60% where the covered lines are the ones that matter — because the first one lies to you and the second one doesn't.</p>
<p>So what I want from a console is line-by-line truth about which branches ran. Not a percentage.</p>
<p>Skip the fifteen-minute YouTube videos. Here's the straight version.</p>
<hr />
<h2>Step 1 — Enable coverage retrieval</h2>
<p>Line-by-line coverage isn't calculated by default.</p>
<ul>
<li><p>Open <strong>Workspace Settings</strong> (<code>Cmd + ,</code> or <code>Ctrl + ,</code>)</p>
</li>
<li><p>Search for <code>retrieve-test-code-coverage</code></p>
</li>
<li><p>Check the box under <strong>Salesforce Apex Testing Configuration</strong></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/34edc345-3f4f-4bae-8ab4-bdbf80ef9c9b.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 2 — Download target classes to your workspace</h2>
<ul>
<li><p>Click the <strong>Org Browser</strong> (the cloud icon with refresh arrows) in the left Activity Bar</p>
</li>
<li><p>Expand <strong>Apex Classes</strong>. This is a call to the org to retrieve the names in that folder, so give it a moment</p>
</li>
<li><p>Find your target class and its test class</p>
</li>
<li><p>Click the <strong>Cloud Download</strong> icon next to each to pull them into the browser workspace</p>
</li>
</ul>
<p>Worth knowing now rather than later: expanding a folder and downloading a file are two separate trips to the org, and you repeat both for every metadata type you need. More on why that matters at the end.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/55ab05bd-2121-4afa-9fba-b52d79c7051b.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 3 — Open the Apex Testing panel</h2>
<ul>
<li><p>Click the <strong>Beaker</strong> icon in the left Activity Bar</p>
</li>
<li><p>This pane lists every test suite and class loaded in your workspace</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/733e843f-0387-4141-ab97-91f82b239486.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 4 — Run your tests</h2>
<ul>
<li>Hover over the test class and click <strong>Play</strong> to run the whole suite, or expand the class to run individual methods</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/80c0a2ee-8b66-4505-98e4-0917e1fe5e2e.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 5 — Watch the results</h2>
<ul>
<li><p>Execution streams into the <strong>Test Results</strong> tab at the bottom</p>
</li>
<li><p>Green checkmarks pass, red indicators are what you're about to go debug</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/f4e7a74e-aa92-43e1-af47-dee752513e6a.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 6 — Read the coverage summary</h2>
<ul>
<li><p>The <strong>Output / Test Results</strong> panel gives you the overall Test Summary — org-wide coverage, duration, pass rate</p>
</li>
<li><p>The <strong>Apex Code Coverage by Class</strong> table gives you per-class percentages and, usefully, the specific uncovered line numbers</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/09abf2e5-56a7-45f7-8b06-771be44afa0a.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/86adcf57-e500-4696-830a-02a8772af5df.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/bc528942-d645-4af7-8ba5-495e892023d7.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 7 — Turn on editor highlighting</h2>
<ul>
<li><p>Open the source file</p>
</li>
<li><p>In the bottom-right status bar, click the <strong>Checklist</strong> icon (<em>Highlight Apex Code</em>)</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/3122c98a-8bed-4143-8101-85104f1ebffd.png" alt="" style="display:block;margin:0 auto" />

<h2>Step 8 — Read the lines</h2>
<p>This is the bit that actually earns its keep. Green is executed, red is not.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6aa40b4d011a85bf7a48aa10/c2272ddc-2800-4c9a-b3e3-1551fa6d6a7a.png" alt="" style="display:block;margin:0 auto" />

<p>Look at what's red in that screenshot. It's a <code>catch (Exception e)</code> block. That's the shape of almost every coverage gap I've ever found: exception handlers, false branches, the path nobody thought about. A percentage would never have told me that. The highlighting does, instantly.</p>
<p><strong>...When it works.</strong></p>
<hr />
<h2>A week later, I went back to the old console</h2>
<p>I said at the top that complaining about change gets you nowhere, and I meant it. So I gave it a real go — four days of actual work, not a tour.</p>
<p>By Friday I had reverted.</p>
<p>I want to be precise about why, because "I don't like it" isn't useful to anybody and it isn't what happened. Here's what happened:</p>
<p><strong>You pay a round trip before you've opened anything.</strong> Expanding a metadata folder in the Org Browser — ApexClass, say — is a call out to the org just to fetch the <em>names</em> of what's in it. Only once that returns can you download the specific classes you actually want into the workspace. Then you do it again for the next folder: triggers, pages, whatever else the problem touches.</p>
<p>So the cost isn't "open a file." It's: wait for the console, wait for a folder listing, choose, download, repeat per folder. In a large org, fetching the names alone is not fast — and you're paying that before you know what you're looking for. Which, when you're debugging, is the entire situation you're in.</p>
<p><strong>Multiply that by every org you touch.</strong> If you're jumping between a few orgs in a day, you would genuinely have to arrange your morning around it: open each one in advance and wait. That's not a workflow, that's a commute.</p>
<p>And it's every dev and full sandbox, because the change landed per org on September 1st — which is also where debugging actually happens.</p>
<p><strong>Then the security improvements bite.</strong> You log in again. And again. And depending on where you land, you may get to re-download the classes you wanted to test against — the ones you already downloaded.</p>
<p><strong>And the coverage itself was inconsistent.</strong> Following the exact steps above, line highlighting did not reliably show me covered lines. Sometimes it worked. Sometimes it didn't, with no obvious reason why.</p>
<p>Which is where I landed on the thing I actually want to say:</p>
<blockquote>
<p><strong>I shouldn't have to debug my debugger.</strong></p>
</blockquote>
<p>I'm not alone in this. Ignacio de Frutos Rosa said it under the original post before I'd written any of this down: <em>"For serious development we already have VS Code. Developer Console was fine for quick log checks and execute anonymous in any org. The new console takes too long to set up for these quick things."</em></p>
<p>That's exactly it, and it's worth separating two different tools that got merged into one. If you're doing serious development you're in a desktop IDE already — you have been for years. The Developer Console was never competing with that. It was the thing you opened for ninety seconds to check a log or run an anonymous block in an org you don't otherwise live in. That job has a hard requirement: <strong>be fast to open.</strong> A browser IDE with a workspace, a download step and a re-auth is a fine tool for a job the Developer Console wasn't doing.</p>
<hr />
<h2>If you need to go back</h2>
<p><strong>Setup → Development → Web Console.</strong> Or just search <code>console</code> in Setup, which is faster. Then toggle the <strong>Enable Developer Console to:</strong> setting.</p>
<p>Two things about that.</p>
<p><strong>You do it per org.</strong> Every developer and full sandbox that rolled over on September 1st needs the toggle flipped individually. There's no org-wide switch, so if you work across several, that's another small tax on top of the ones above.</p>
<p><strong>Production hasn't been forced yet.</strong> At time of writing it still lists this as <strong>Web Console (Beta)</strong> and leaves the old console in place.</p>
<p>Which is worth sitting with for a second, because the rollout order is backwards for this particular tool. Production is where you're <em>least</em> likely to be poking at Apex all day. Sandboxes are where debugging actually happens — where you're jumping between orgs, checking a log, running an anonymous block, chasing something down. Salesforce forced the change exactly where the fast-open use case matters most, and left it optional where it barely matters at all.</p>
<p>I'd still say learn the new one. The legacy console is going away eventually, "eventually" always arrives, and doing it under deadline is worse than doing it now. Everything in the eight steps above works — I wrote them down precisely so the next person doesn't lose a morning to it.</p>
<p>But there's a difference between refusing to adapt and reporting a measurement. I adapted. Then I measured. The tool that's replacing the fast one isn't fast yet.</p>
<p>I'll try again at Spring '27.</p>
<hr />
<p><em>Nineteen years of Salesforce, mostly spent reading debug logs. I also build</em> <a href="https://saasylogs.com"><em>Saasy Logs</em></a><em>, a free Apex debug log analyzer, for exactly the reason you'd expect.</em></p>
<p><em>A version of this first appeared on LinkedIn.</em></p>
]]></content:encoded></item></channel></rss>