<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dev Encyclopedia</title>
    <description>The latest articles on DEV Community by Dev Encyclopedia (@dev_encyclopedia).</description>
    <link>https://dev.to/dev_encyclopedia</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3960190%2F006fbb41-1855-46cb-a641-7e9f5326421e.png</url>
      <title>DEV Community: Dev Encyclopedia</title>
      <link>https://dev.to/dev_encyclopedia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev_encyclopedia"/>
    <language>en</language>
    <item>
      <title>Your RLS Policy Passed Its Test For the Wrong Reason</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Fri, 21 Aug 2026 12:47:06 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/your-rls-policy-passed-its-test-for-the-wrong-reason-2oah</link>
      <guid>https://dev.to/dev_encyclopedia/your-rls-policy-passed-its-test-for-the-wrong-reason-2oah</guid>
      <description>&lt;p&gt;A manual psql check answers exactly one question: does this policy work right now, against today's schema, with today's roles. It says nothing about tomorrow.&lt;/p&gt;

&lt;p&gt;Three ordinary changes are enough to quietly break tenant isolation without anyone noticing at review time. A migration that drops and recreates a table loses RLS entirely, since it's a per-table flag, not something that travels with column definitions. A new service role for a background job can skip the policy if nobody remembers to apply it. And the most common one: someone grants BYPASSRLS during an incident and never revokes it.&lt;/p&gt;

&lt;p&gt;Most guides point you at pgTAP here and stop. pgTAP is fine, but it's a separate SQL-based framework with its own runner. If your backend is already on Jest, you don't need a second test framework, you need a Jest test that actually proves a leak can't happen. The core pattern: seed a row as tenant A, query as tenant B, assert the result is empty. Run it through a dedicated low-privilege role, since table owners and superusers bypass RLS by default even with FORCE enabled for the owner.&lt;/p&gt;

&lt;p&gt;I break down the full pattern, the queryAsTenant helper, testing WITH CHECK on INSERT/UPDATE, catching accidental BYPASSRLS grants, and wiring it into GitHub Actions here: &lt;a href="https://devencyclopedia.com/blog/postgres-rls-testing-jest" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/postgres-rls-testing-jest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're doing this across more than one or two tables, I also built RLSBuilder, a browser tool that generates the CREATE POLICY SQL and a matching Jest test from the same three inputs so they can't drift apart: &lt;a href="https://devencyclopedia.com/tools/rls-builder" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/rls-builder&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>testing</category>
      <category>jest</category>
      <category>security</category>
    </item>
    <item>
      <title>Stop Writing Your Mongoose Schema Twice: InferSchemaType, HydratedDocument, and the populate() Fix Nobody Explains</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Tue, 18 Aug 2026 04:51:28 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/stop-writing-your-mongoose-schema-twice-inferschematype-hydrateddocument-and-the-populate-fix-eme</link>
      <guid>https://dev.to/dev_encyclopedia/stop-writing-your-mongoose-schema-twice-inferschematype-hydrateddocument-and-the-populate-fix-eme</guid>
      <description>&lt;p&gt;If you've added TypeScript to a Mongoose project, you've probably written the same shape twice, once as an interface, once as the schema that actually enforces it at runtime. They don't check each other. Add a field to the schema and forget the interface, and TypeScript won't catch it, because as far as the type checker knows, the interface is correct. It's just wrong relative to what actually gets saved to MongoDB.&lt;/p&gt;

&lt;p&gt;InferSchemaType fixes that duplication, it derives the plain data shape straight from the schema. But it only gets you the data shape. It doesn't know about .save(), it doesn't know about ._id, and it has no idea what Mongoose attaches to a document once it comes back from a query. That's where HydratedDocument comes in, and skipping it is the single most common reason people end up reaching for "as any" on a perfectly normal query result.&lt;/p&gt;

&lt;p&gt;Then there's the part that trips up almost everyone eventually: .populate(). By default a referenced field types as a raw ObjectId, even after you've populated it. TypeScript has no way to see that a runtime call changed the shape of your result. There's an open GitHub issue on Mongoose's own repo about exactly this, with no canonical fix linked anywhere easy to find.&lt;/p&gt;

&lt;p&gt;I break down the full fix, plus typing instance methods, statics, virtuals, and when you should still hand-write an interface, here: &lt;a href="https://devencyclopedia.com/blog/mongoose-typescript-interfaces" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/mongoose-typescript-interfaces&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you just want the interface and populate snippet generated for your actual schema instead of reconstructing the generics from memory, I also built a free browser tool for that: &lt;a href="https://devencyclopedia.com/tools/mongoosets" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/mongoosets&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>mongodb</category>
      <category>node</category>
      <category>mern</category>
    </item>
    <item>
      <title>Mongoose 9 Migration Guide: What Actually Breaks in a Real MERN App</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Sun, 16 Aug 2026 11:35:16 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/mongoose-9-migration-guide-what-actually-breaks-in-a-real-mern-app-4p18</link>
      <guid>https://dev.to/dev_encyclopedia/mongoose-9-migration-guide-what-actually-breaks-in-a-real-mern-app-4p18</guid>
      <description>&lt;p&gt;If you run npm update on a Mongoose 8 project without a pinned version, you might land on Mongoose 9 without meaning to. And depending on your codebase, that upgrade can go wrong in ways your test suite won't catch.&lt;/p&gt;

&lt;p&gt;The headline change is that Mongoose 9 drops callback support from pre() hooks entirely. Any hook shaped like schema.pre('save', function(next) { ... next(); }) still runs, but next() is now a silent no-op. No thrown error, no console warning, just code after the hook that stops firing the way it used to.&lt;/p&gt;

&lt;p&gt;That alone is grep-and-fix work. The riskier part is what it does to plugins you didn't write. Auth and validation packages like mongoose-unique-validator and passport-local-mongoose attach their own internal pre-save hooks. If a plugin's version predates confirmed Mongoose 9 support, its hook can silently stop doing its job, meaning duplicate key errors that used to get converted into clean ValidationErrors start reaching your API responses raw.&lt;/p&gt;

&lt;p&gt;On top of that, ObjectId construction got stricter, and Mongoose's generated TypeScript types now check query filters more aggressively against your schema shape, so a clean tsc run before the upgrade won't necessarily stay clean after.&lt;/p&gt;

&lt;p&gt;I break down all of this with a practical six-step upgrade order, how to write tests that actually catch a silently skipped hook, and a safe rollback plan here: &lt;a href="https://devencyclopedia.com/blog/mongoose-9-migration-guide" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/mongoose-9-migration-guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>mongoose</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>CSS @scope Is Baseline Now. Here's a Playground to Actually See How It Works</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Fri, 07 Aug 2026 03:38:16 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/css-scope-is-baseline-now-heres-a-playground-to-actually-see-how-it-works-106g</link>
      <guid>https://dev.to/dev_encyclopedia/css-scope-is-baseline-now-heres-a-playground-to-actually-see-how-it-works-106g</guid>
      <description>&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; reached Baseline in December 2025, which means Chrome, Edge, Safari, and Firefox all ship it in stable. That's great news, except most explanations of &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; are still static code blocks, and a scoping rule is exactly the kind of feature that's hard to reason about without watching it run.&lt;/p&gt;

&lt;p&gt;So I built ScopeLab, a live editor for &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt;. You write HTML in one pane and CSS in the other, and the browser's own &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; engine renders the result inside a sandboxed iframe. No polyfill, no custom parser standing between your code and the outcome.&lt;/p&gt;

&lt;p&gt;The interesting part is the highlight layer. It reads the scope root and optional limit straight out of your first &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; rule and draws outlines accordingly: solid green for the root, dashed green for in-scope descendants, dashed red for anything past a scope limit. Because that highlight is itself implemented as an &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; rule, it can never disagree with what the browser is actually doing.&lt;/p&gt;

&lt;p&gt;There's also a Without &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; toggle that strips the wrappers so the same selectors apply globally, which is the fastest way to see the exact leak that &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt; was built to stop.&lt;/p&gt;

&lt;p&gt;If you've ever been unsure how scope limits create a "donut scope," or how proximity to the scope root affects specificity ties, this is built to make that click. I walk through the syntax reference and real scoping scenarios (component containment, protecting nested widgets, excluding third-party iframes) here: &lt;a href="https://devencyclopedia.com/tools/scopelab" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/scopelab&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>baseline</category>
    </item>
    <item>
      <title>Why Two GraphQL Queries Against the Same Schema Can Differ in Cost by 1000x</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Thu, 06 Aug 2026 04:34:46 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/why-two-graphql-queries-against-the-same-schema-can-differ-in-cost-by-1000x-gpe</link>
      <guid>https://dev.to/dev_encyclopedia/why-two-graphql-queries-against-the-same-schema-can-differ-in-cost-by-1000x-gpe</guid>
      <description>&lt;p&gt;REST has a nice property: each endpoint has a roughly fixed cost. GraphQL throws that out. A single query can request arbitrarily deep and wide data, so two queries hitting the exact same schema can differ in resolution cost by orders of magnitude.&lt;/p&gt;

&lt;p&gt;That flexibility cuts both ways. A tiny query string, whether crafted by an attacker or introduced by an accidental infinite nesting bug, can force a server to resolve millions of objects. This is why every major GraphQL server library ships some form of complexity analysis, and why knowing a query's cost before it hits production actually matters.&lt;/p&gt;

&lt;p&gt;The core mechanic is simpler than it sounds: every field starts at a base cost of 1, list fields (anything with a first/last/limit argument, or that just looks like a collection) become multipliers, and a field's final cost is the product of every list ancestor above it. Nesting compounds fast. One deeply nested list field with a couple of first:N arguments stacked on top of each other can dominate the entire score.&lt;/p&gt;

&lt;p&gt;I built QueryWeight to make this visible without doing the math by hand. Paste a query, get the AST-parsed depth, complexity score, unbounded list flags, and a ranked breakdown of what's actually driving the number, all computed client-side with zero network calls.&lt;/p&gt;

&lt;p&gt;Full breakdown of the scoring model and how to read the results here: &lt;a href="https://devencyclopedia.com/tools/queryweight" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/queryweight&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>api</category>
      <category>webdev</category>
      <category>devtools</category>
    </item>
    <item>
      <title>I Built a Tool That Explains MongoDB Aggregation Pipelines Without Touching a Database</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Wed, 05 Aug 2026 03:29:53 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/i-built-a-tool-that-explains-mongodb-aggregation-pipelines-without-touching-a-database-ioj</link>
      <guid>https://dev.to/dev_encyclopedia/i-built-a-tool-that-explains-mongodb-aggregation-pipelines-without-touching-a-database-ioj</guid>
      <description>&lt;p&gt;If you've ever opened a PR with a five-stage aggregation pipeline and had to reconstruct what it does in your head, you know the drill: trace the $match, figure out what the $group collapses, work out whether that $lookup is even necessary, all without a database connection to actually run it against.&lt;/p&gt;

&lt;p&gt;That's the exact gap PipelineExplain fills. Paste your pipeline array (strict JSON or Mongo shell syntax with unquoted keys and constructors like ObjectId(...) and ISODate(...)) and it parses it locally in your browser, then explains each stage in plain English using your actual field names and group keys, not a generic placeholder.&lt;/p&gt;

&lt;p&gt;It also groups consecutive stages into categories like filter, group, join, and reshape, so you get a one-line shape summary of the whole pipeline before diving into stage-by-stage detail. And it scans for the classic performance traps: a late $match, a $sort running before a $group, or a $lookup that might be more expensive than it looks.&lt;/p&gt;

&lt;p&gt;The tool never connects to a real database and never executes anything, so the "before/after" examples are illustrative, not your actual documents. For that, you'd still reach for Compass or the shell. But for the moment you're reading someone else's pipeline in a PR or a Stack Overflow thread with no DB handy, this is built for exactly that.&lt;/p&gt;

&lt;p&gt;Full breakdown of supported syntax and stage coverage here: &lt;a href="https://devencyclopedia.com/tools/pipelineexplain" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/pipelineexplain&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>nosql</category>
      <category>webdev</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Your Crate's MSRV Is Probably Wrong (And You Won't Know Until Someone's Build Breaks)</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:48:09 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/your-crates-msrv-is-probably-wrong-and-you-wont-know-until-someones-build-breaks-571n</link>
      <guid>https://dev.to/dev_encyclopedia/your-crates-msrv-is-probably-wrong-and-you-wont-know-until-someones-build-breaks-571n</guid>
      <description>&lt;p&gt;Here's a scenario that plays out constantly in Rust projects: your Cargo.toml declares &lt;code&gt;rust-version = "1.70"&lt;/code&gt;, your CI is green, your tests pass. Then a contributor on an older pinned toolchain opens an issue because their build fails on a syntax error you've never seen.&lt;/p&gt;

&lt;p&gt;Somewhere between when you set that rust-version and now, a PR quietly introduced a feature that needs something newer. Maybe it was a &lt;code&gt;let-else&lt;/code&gt; statement. Maybe someone swapped in &lt;code&gt;OnceLock&lt;/code&gt; instead of the &lt;code&gt;once_cell&lt;/code&gt; crate. Nothing failed locally because your own toolchain is newer than what you claim to support.&lt;/p&gt;

&lt;p&gt;The tricky part is that Rust features fall into different categories with very different implications. Syntax changes like let-else won't parse at all on an older compiler, full stop. Standard library additions like &lt;code&gt;Option::is_some_and&lt;/code&gt; often have a crate-based equivalent you can swap in. Trait system changes like generic associated types or native async fn in traits are usually the hardest to walk back since they change what the compiler can express.&lt;/p&gt;

&lt;p&gt;I built a small browser tool that pattern-matches pasted Rust source or a Cargo.toml against a feature lookup table spanning Rust 1.60 through 1.82, and reports the newest feature it finds, since that's your actual floor. It also cross-checks a declared &lt;code&gt;rust-version&lt;/code&gt; against what it detects and flags the mismatch.&lt;/p&gt;

&lt;p&gt;It's a heuristic, not a compiler, so it won't replace cargo-msrv for a final release check. But for eyeballing a PR or a new dependency before you commit real time to it, it's instant. I walk through how it handles trait blocks and the async-trait macro distinction here: &lt;br&gt;
&lt;a href="https://devencyclopedia.com/tools/msrvcheck" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/msrvcheck&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>rusting</category>
      <category>devtools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Kubernetes Swap Support in 1.35: The Config That Silently Does Nothing</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Sun, 02 Aug 2026 05:17:02 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/kubernetes-swap-support-in-135-the-config-that-silently-does-nothing-2deb</link>
      <guid>https://dev.to/dev_encyclopedia/kubernetes-swap-support-in-135-the-config-that-silently-does-nothing-2deb</guid>
      <description>&lt;p&gt;Node swap support (KEP-2400) went GA in 1.34 and stable in 1.35. If you've been putting off a decision on this, this is the release where it's actually safe to test.&lt;/p&gt;

&lt;p&gt;But "stable" doesn't mean "on for you." Swap is opt-in at two levels: swap has to be provisioned on the node's disk, and the kubelet has to be explicitly configured to allow it. Nothing changes just because you upgraded.&lt;/p&gt;

&lt;p&gt;Here's the trap. Setting failSwapOn: false gets you NoSwap by default, which just stops the kubelet from refusing to start on a swap-enabled node. Your pods still don't get swap access. People provision swap, flip failSwapOn, restart the kubelet, and wonder why nothing changed. The setting you actually need is memorySwap.swapBehavior: LimitedSwap.&lt;/p&gt;

&lt;p&gt;There's also a QoS restriction that trips people up: only Burstable pods (where at least one container's memory request is below its limit) get swap access at all. Guaranteed pods are excluded by design, and BestEffort pods never get it either.&lt;/p&gt;

&lt;p&gt;In the full writeup I cover the cgroup v2 and container runtime prerequisites, the exact kubelet config, how to verify it actually worked (not just that the kubelet accepted it), and a breakdown of workload types where this helps versus where it makes p99 latency worse: &lt;a href="https://devencyclopedia.com/blog/kubernetes-swap-support-1-35" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/kubernetes-swap-support-1-35&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloudnative</category>
      <category>linux</category>
    </item>
    <item>
      <title>Earning the July 2026 GitHub Actions Top Reader Badge! 🏆</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Sat, 01 Aug 2026 11:15:47 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/earning-the-july-2026-github-actions-top-reader-badge-1g2i</link>
      <guid>https://dev.to/dev_encyclopedia/earning-the-july-2026-github-actions-top-reader-badge-1g2i</guid>
      <description>&lt;p&gt;Hey DEV community! 👋&lt;/p&gt;

&lt;p&gt;I’m thrilled to share that I just received the &lt;strong&gt;July 2026 Top Reader Badge for GitHub Actions&lt;/strong&gt; from DevEncyclopedia!&lt;/p&gt;

&lt;p&gt;As a software engineer, I'm always looking to streamline my CI/CD workflows, improve how I handle automation, and optimize my project deployments. Spending time this month diving deep into GitHub Actions tutorials and resources has been incredibly rewarding. Continuous learning is such a core part of what we do in tech, and it's an awesome feeling to have that dedication recognized.&lt;/p&gt;

&lt;p&gt;A huge thank you to the authors and creators who put together these fantastic resources. If you haven't checked them out yet, I highly encourage you to explore and keep leveling up your skills.&lt;/p&gt;

&lt;p&gt;What new tech or tools are you all learning this month? Let me know below! 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7grozlcadvepswqg3ae.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7grozlcadvepswqg3ae.webp" alt="July 2026 Top Reader Badge for GitHub Actions from DevEncyclopedia" width="640" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>learning</category>
      <category>devencyclopedia</category>
    </item>
    <item>
      <title>Building Native Desktop Apps with Deno 2.9 and Pure TypeScript</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Fri, 31 Jul 2026 04:14:21 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/building-native-desktop-apps-with-deno-29-and-pure-typescript-2cke</link>
      <guid>https://dev.to/dev_encyclopedia/building-native-desktop-apps-with-deno-29-and-pure-typescript-2cke</guid>
      <description>&lt;p&gt;Shipping a web application as a desktop binary has traditionally required significant compromises. Electron developers deal with massive binary sizes due to bundled Chromium instances, while Tauri developers face a steep learning curve by being forced to write backend logic in Rust. For teams completely standardized on TypeScript, neither approach feels entirely seamless.&lt;/p&gt;

&lt;p&gt;Deno 2.9 addresses this gap by introducing deno desktop, a canary feature that lets you package a Deno web project into a native desktop application using only TypeScript. Instead of manually wiring up ports or managing inter-process communication boundaries, you can point the command directly at your server. Better yet, the framework supports a window.bind API that bridges page JavaScript straight to backend functions with zero HTTP overhead.&lt;/p&gt;

&lt;p&gt;Whether you are targeting macOS, Windows, or Linux, the workflow stays firmly within the runtime you already know. I break down the full tutorial, configuration, and native API bindings here: &lt;a href="https://devencyclopedia.com/blog/deno-desktop-tutorial" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/deno-desktop-tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>deno</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stop Guessing What Your Cron Expression Actually Does</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Thu, 30 Jul 2026 03:54:04 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/stop-guessing-what-your-cron-expression-actually-does-4h88</link>
      <guid>https://dev.to/dev_encyclopedia/stop-guessing-what-your-cron-expression-actually-does-4h88</guid>
      <description>&lt;p&gt;If you've ever stared at "0 9 * * 1-5" and had to mentally reconstruct which field is which, you're not alone. Cron syntax is compact by design, which makes it great for config files and terrible for readability.&lt;/p&gt;

&lt;p&gt;The real problems show up once you leave plain Linux crontab. GitHub Actions runs everything in UTC regardless of your repo's timezone, and it silently ignores any schedule more frequent than every 5 minutes, no error, it just won't fire as often as you asked. AWS EventBridge adds a 6-field format with seconds and year, plus its own rate() syntax. Kubernetes CronJobs look identical to standard 5-field cron but run in the pod's timezone, which defaults to UTC unless you set it explicitly.&lt;/p&gt;

&lt;p&gt;Then there's the logic trap: when both the day-of-month and day-of-week fields are restricted at the same time, cron doesn't AND them together, it ORs them. So an expression meant to mean "first Monday of the month" actually fires on the 1st of the month OR every Monday, whichever comes first.&lt;/p&gt;

&lt;p&gt;I put together a free Cron Expression Builder that translates any expression into plain English, shows your next 5 scheduled run times in your local timezone, and breaks down the platform-specific quirks above. I break down all of it here: &lt;a href="https://devencyclopedia.com/tools/cron-builder" rel="noopener noreferrer"&gt;https://devencyclopedia.com/tools/cron-builder&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cron</category>
      <category>kubernetes</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>How to Switch to uv: Replace pip, virtualenv, and Poetry in Your Python Project</title>
      <dc:creator>Dev Encyclopedia</dc:creator>
      <pubDate>Wed, 29 Jul 2026 07:18:42 +0000</pubDate>
      <link>https://dev.to/dev_encyclopedia/how-to-switch-to-uv-replace-pip-virtualenv-and-poetry-in-your-python-project-41p5</link>
      <guid>https://dev.to/dev_encyclopedia/how-to-switch-to-uv-replace-pip-virtualenv-and-poetry-in-your-python-project-41p5</guid>
      <description>&lt;p&gt;If you've worked on a Python project for more than a year, you know the drill: pip to install packages, virtualenv or venv to isolate environments, pyenv to manage Python versions, and pip-tools to generate a lockfile. Four separate tools, four config formats, and four different points of failure in CI.&lt;/p&gt;

&lt;p&gt;uv, built by Astral (the team behind ruff), collapses all of that into a single Rust binary. It's not a modest speed bump either, we're talking 10 to 100x faster than pip on cold installs and near-instant on warm ones. In CI, where the cache is cold on every run, that difference is often the gap between a multi-minute install and one that finishes in seconds.&lt;/p&gt;

&lt;p&gt;This isn't a "starting fresh" tutorial. It's specifically about migrating a project that already has a requirements.txt or a Poetry-based pyproject.toml, since that's the situation most of us are actually in.&lt;/p&gt;

&lt;p&gt;The guide covers the real friction points: importing an existing requirements.txt cleanly (there's a one-liner for simple files and a safer fallback for ones with pins, comments, or extras), migrating off Poetry with a dedicated conversion tool, what doesn't auto-migrate (dependency groups, private indexes, poetry run calls), pinning your Python version so the whole team and CI stay in sync, and wiring up GitHub Actions with the one flag that keeps your lockfile honest.&lt;/p&gt;

&lt;p&gt;I break down every step, plus the actual benchmark numbers, here: &lt;a href="https://devencyclopedia.com/blog/switch-to-uv-python" rel="noopener noreferrer"&gt;https://devencyclopedia.com/blog/switch-to-uv-python&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>productivity</category>
      <category>devops</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
