Best of General ProgrammingDecember 2025

  1. 1
    Article
    Avatar of vigetViget·22w

    Fixing TypeScript Performance Problems: A Case Study

    A TypeScript monorepo was experiencing severe performance issues with 6+ minute build times and sluggish intellisense. Using compiler diagnostics, trace analysis, and the @typescript/analyze-trace tool, the team identified that kysely helper functions with complex type inference were causing 80-second type-checking bottlenecks. By inlining these queries, removing circular dependencies, eliminating barrel files, and cleaning up unused types, they reduced build time by 79% (from 6.2 to 1.3 minutes), cut memory usage in half, and restored responsive editor performance.

  2. 2
    Article
    Avatar of goserverlessServerless·23w

    CI/CD for monorepos

    Serverless Framework Pro's CI/CD solution supports deploying multiple services from a single monorepo. Services should be organized in separate subdirectories off the root, with each service configured with the same app and org settings. After initial deployment via CLI, connect your GitHub or BitBucket repository and configure branch-to-stage mappings for automated deployments. Advanced features include selective deployments (only redeploy when specific service code changes) and dependency-based deployments (redeploy when dependent services or shared code folders are modified). This approach provides flexibility to deploy only what's needed based on code changes.

  3. 3
    Article
    Avatar of threedotslabsThree Dots Labs·24w

    DDD: A Toolbox, Not a Religion

    Domain-Driven Design (DDD) should be treated as a flexible toolbox rather than an all-or-nothing methodology. Most software projects fail due to poor handling of business domain complexity, not technical challenges. The core principle is understanding and modeling the business domain well in code, with strategic patterns (like bounded contexts and core domains) being universally valuable, while tactical patterns should only be applied when they solve actual problems. Developers often over-focus on technical complexity and frameworks instead of domain understanding, leading to legacy code. The key is pragmatically selecting DDD patterns that address real issues in your specific context, avoiding both religious adherence and complete dismissal of the approach.

  4. 4
    Article
    Avatar of seangoedeckesean goedecke·21w

    You can't design software you don't work on

    Generic software design advice is largely useless for real-world engineering work on large existing codebases. Effective design requires intimate knowledge of concrete implementation details, not abstract principles. The most valuable design discussions happen between engineers actively working on the system, focusing on specific subsystems, dependencies, and constraints. Generic advice has limited utility: guiding new projects, tie-breaking decisions, and ensuring cross-codebase consistency. Formal architect roles that design without implementation responsibility often fail because they lack the concrete understanding needed to create actionable plans. Engineers who design systems should be accountable for their success or failure.

  5. 5
    Article
    Avatar of devtoDEV·23w

    My OSS Stalled for 3 Months Because of Misguided Vibe Coding—This Is the Full Reboot Story

    A developer shares their experience recovering from a 3-month project stall on diffx, a structured-data diff tool. The root causes included monorepo complexity, over-sharing CI/CD infrastructure across multiple projects, premature multilingual documentation, and quality issues from AI-assisted "vibe coding" without proper verification. The recovery process involved quarantining existing code, manually verifying functionality, writing specs from scratch, rebuilding tests based on specs rather than implementation, and splitting the monorepo into separate language-specific repositories. Key lessons include the importance of spec-driven development with AI, two-stage release workflows, and having the courage to delete broken artifacts rather than clinging to sunk costs.

  6. 6
    Video
    Avatar of youtubeYouTube·24w

    Zig got better and I almost missed it

    Zig 0.15 brings major improvements including a self-hosted x86 backend (up to 5× faster debug builds), 50% speedup from threaded codegen, and removal of async/await keywords. The standard library underwent significant changes with non-generic Reader/Writer interfaces ("Writergate"), unmanaged ArrayList as default, and HTTP client/server reworks. Language changes include switch support for non-exhaustive enums, usingnamespace removal, and stricter int-to-float casting. The build system adds a web UI and improved templates. Future plans include AArch64 backend, incremental compilation, and a new I/O interface for colorless async.

  7. 7
    Article
    Avatar of matkladmatklad·24w

    Do Not Optimize Away

    Compilers like LLVM can optimize away code during benchmarking by replacing computations with closed-form expressions or eliminating unused results entirely. Instead of relying on functions like Rust's `hint::black_box` or Zig's `mem.doNotOptimizeAway`, a more reliable approach is to make input parameters runtime-overridable (preventing constant folding) and print computation results or their hashes (preventing dead code elimination). This method prevents compiler optimizations from invalidating benchmarks while providing bonus features like easy parameter tuning and immediate detection of incorrect optimizations through hash mismatches.

  8. 8
    Article
    Avatar of hnHacker News·21w

    The Compiler Is Your Best Friend, Stop Lying to It

    Compilers are powerful tools that developers often underutilize by "lying" through null values, unchecked exceptions, type casts, and untracked side-effects. By making implicit assumptions explicit in the type system—using Option types instead of null, Result types for errors, sealed/union types instead of casts, and separating pure functions from side-effects—developers enable the compiler to catch bugs at compile-time rather than in production. Techniques like typed wrappers for domain concepts, union types for modeling valid states, and encoding guarantees as types transform the compiler from an adversary into a collaborative partner that tracks invariants, guides refactoring, and prevents entire classes of runtime errors.