BFS vs DFS: Traversal Order and Data Structure

Overview Both are algorithms for visiting every node in a tree or graph, but they differ in which node they explore next. BFS spreads outward level by level using a queue, while DFS plunges down one path as far as possible before backtracking, using a stack. Comparison Diagram BFSDFS12345671253467outinQueue (FIFO)push/popStack (LIFO) Comparison Table Aspect BFS DFS Underlying structure Queue (FIFO) Stack (FILO), often via recursion Traversal pattern Explores all neighbors at current depth before going deeper Follows one branch to its end before backtracking Order nodes are visited Level by level (breadth-first) Branch by branch (depth-first) Memory usage O(width) — can be large for wide/bushy graphs O(depth) — can be large for deep graphs Shortest path guarantee Yes, on unweighted graphs (first visit = shortest path) No, may find a longer path first Implementation style Iterative with explicit queue Recursive, or iterative with explicit stack Risk of infinite loop Low with visited-set on cyclic graphs Higher on cyclic graphs without visited-set, or infinite depth Typical use cases Shortest path, level-order processing, web crawling by hops Topological sort, cycle detection, maze/backtracking problems Key Differences BFS uses a queue and expands outward level by level, while DFS uses a stack (or recursion) and dives deep before backtracking. BFS guarantees the shortest path on unweighted graphs; DFS does not. BFS memory cost scales with graph width, while DFS memory cost scales with graph depth. DFS naturally supports backtracking algorithms like maze solving and topological sort. Both require a visited set to avoid infinite loops on cyclic graphs. When to Use Each BFS ...

August 2, 2026 · 2 min · 388 words · jeonck

Two Pointers vs Sliding Window: Choosing the Right Array Scanning Technique

Overview Two Pointers and Sliding Window are both O(n) techniques for scanning arrays or strings, but they solve different shapes of problems: Two Pointers tracks two independent indices that move toward, away from, or alongside each other, while Sliding Window maintains a contiguous subrange that expands and contracts as it scans. Picking the wrong one usually means either overcomplicating a pair-search problem or missing the running aggregate a window naturally provides. Comparison Diagram Two PointersSliding WindowLRindices converge inwardover sorted dataLRcontiguous range expands/contracts, tracking an aggregate Comparison Table Aspect Two Pointers Sliding Window Core mechanism Two independent indices scan or converge across the data Two indices (left/right) define a contiguous range that grows and shrinks Pointer movement Move toward each other, away, or in lockstep at a fixed offset Right pointer expands the range forward, left pointer contracts it Input requirement Usually needs sorted data or a paired structure Works on any unsorted array or string State tracked Just the two positions and the values being compared A running aggregate of window contents (sum, count, frequency map) Problem signature Pair-sum, palindrome check, merging two sorted arrays Longest/shortest substring or max/min sum under a constraint Relationship between pointers No notion of a range between them, only the two positions matter The range between the pointers IS the answer candidate Time and space complexity O(n) time, O(1) space O(n) time, O(1) to O(k) space for the aggregate Failure mode Breaks if data isn’t sorted or orderable for the comparison Breaks if the target condition isn’t monotonic, so the window can’t shrink safely Key Differences Two Pointers tracks two independent indices; Sliding Window tracks a contiguous range between them. Two Pointers typically requires sorted input; Sliding Window works fine on unsorted sequences. Sliding Window maintains a running aggregate as it moves; Two Pointers usually just compares individual values. Sliding Window breaks down when the target condition isn’t monotonic, since the window can’t be safely shrunk. When to Use Each Two Pointers ...

August 2, 2026 · 3 min · 460 words · jeonck

Terraform vs Ansible: Provisioning vs Configuration Management

Overview Terraform and Ansible are both infrastructure-as-code tools but solve different problems: Terraform declaratively provisions and tracks cloud infrastructure using a state file, while Ansible procedurally configures and manages software on existing hosts with no persistent state. Many teams use them together — Terraform to stand up infrastructure, Ansible to configure it. Comparison Diagram Terraformdeclarativemain.tf (desired state)state file (source of truth)dependency graphVMNetworkDBconverges infra to match stateAnsibleproceduralplaybook.ymltask 1: install pkgtask 2: configuretask 3: start serviceServer AServer BServer Csequential push over SSH, no state file Comparison Table Aspect Terraform Ansible Primary purpose Provision and tear down cloud/infra resources (VMs, networks, DBs) Configure software and manage state on existing hosts Configuration language HCL (HashiCorp Configuration Language), declarative YAML playbooks, procedural task lists Execution model Builds a dependency graph and applies changes in parallel where possible Executes tasks sequentially, in order, per host State management Maintains a state file mapping config to real resources Stateless — queries live system facts on each run Idempotency approach Diffs desired config against state file before acting Each module checks current condition before making a change Connectivity/agent requirement Agentless — calls cloud/provider APIs directly Agentless — connects over SSH or WinRM to target hosts Failure & recovery handling Partial applies are resolved by re-running against the state file Reruns the playbook from the start; tasks are re-checked, not resumed Key Differences Terraform tracks infrastructure in a persistent state file; Ansible has no state store and reads live system facts each run. Terraform resolves a dependency graph to apply changes in parallel; Ansible runs tasks sequentially. Terraform talks to infrastructure through provider APIs; Ansible connects to hosts via SSH/WinRM. Terraform is built for provisioning infra; Ansible is built for configuration of what already exists. They’re commonly paired: Terraform creates the servers, then Ansible configures them. When to Use Each Terraform ...

August 2, 2026 · 3 min · 455 words · jeonck

Role vs ClusterRole: Kubernetes RBAC Scope Compared

Overview Role and ClusterRole are both Kubernetes RBAC objects that define sets of permission rules (verbs on resources), but they differ in scope: a Role only applies within a single namespace, while a ClusterRole is defined once for the whole cluster and can be bound either cluster-wide or scoped down to one namespace. Understanding this distinction is essential for applying least-privilege access control in multi-tenant clusters. Comparison Diagram RoleClusterRoleNamespace: devRoleRoleBindingUserlimited to this namespaceCluster scopeClusterRoleRoleBindingClusterRoleBindingUserthis ns onlyUserall namespacesone definition, reused via either binding Comparison Table Aspect Role ClusterRole API object scope Namespaced object; exists only within one Namespace Cluster-scoped object; exists once for the entire cluster Resources it can grant access to Only namespaced resources (pods, configmaps, secrets, etc.) within its own namespace Namespaced resources cluster-wide plus cluster-scoped resources such as nodes, persistentvolumes, and namespaces Non-resource URLs (e.g. /healthz, /metrics) Cannot reference non-resource URLs Can include rules for non-resource URLs Binding object required RoleBinding only, created in the same namespace RoleBinding for a namespace-scoped grant, or ClusterRoleBinding for a cluster-wide grant Effective grant when bound Permissions always limited to the Role’s own namespace Spans every namespace when bound via ClusterRoleBinding, or just one namespace when bound via RoleBinding Reuse across namespaces Must be duplicated in each namespace that needs the same rules Defined once, reused across many namespaces or cluster-wide via separate bindings Aggregation support None; rules are static within the object Supports aggregationRule to auto-combine rules from other ClusterRoles by label selector Typical built-in examples None shipped by default; teams author their own per namespace cluster-admin, admin, edit, view, and system: component roles ship as default ClusterRoles Key Differences Role is namespace-scoped while ClusterRole is cluster-scoped by definition, regardless of how it’s later bound. Only ClusterRole can grant access to cluster-scoped resources like nodes or to non-resource URLs such as /metrics. A ClusterRole can still be restricted to one namespace by binding it with a RoleBinding instead of a ClusterRoleBinding. ClusterRole supports aggregation to compose permissions from labeled ClusterRoles; Role has no equivalent mechanism. Kubernetes ships default admin/edit/view permission sets as built-in ClusterRoles, never as Roles. When to Use Each Role ...

August 2, 2026 · 3 min · 520 words · jeonck

RBAC vs ABAC: Role-Based vs Attribute-Based Access Control

Overview RBAC and ABAC are two models for deciding whether a subject can perform an action on a resource. RBAC grants access based on a user’s assigned role and that role’s fixed permission set, while ABAC evaluates a policy against attributes of the user, resource, action, and environment at request time. The choice affects how fine-grained, dynamic, and auditable your authorization system can be. Comparison Diagram RBACABACUserRole: EditorPermissionsReadWritePublishFixed, regardless of contextUser attrsResource attrsEnv attrsPolicy EngineAllow / DenyEvaluated per request, in context Comparison Table Aspect RBAC ABAC Access decision basis A user’s assigned role Attributes of the user, resource, action, and environment Permission structure Static, predefined role-to-permission mappings Dynamic policies expressed as attribute-based rules Administration Admin assigns users to existing roles Policy author writes rules combining attribute conditions Runtime evaluation Check whether the user’s role includes the requested permission Policy engine evaluates rules against current attribute values Context sensitivity Same result regardless of time, location, or device Can factor in time, location, device, and other real-time signals Granularity Coarse-grained, applied per role Fine-grained, applied per request or condition Scalability with complexity Role explosion as requirements diversify Policy complexity grows, but avoids proliferating roles Auditability Easy to audit — list who holds a given role Harder to audit — requires tracing policy logic across attributes Key Differences RBAC ties access to roles; ABAC ties access to attributes RBAC decisions are static; ABAC decisions are context-aware ABAC enables fine-grained control at the cost of policy complexity RBAC suffers from role explosion as requirements grow RBAC is generally easier to audit than ABAC When to Use Each RBAC ...

August 2, 2026 · 3 min · 427 words · jeonck

SIGTERM vs SIGKILL: Graceful vs Forced Process Termination

Overview SIGTERM and SIGKILL are both Unix signals used to stop a running process, but they differ in whether the process gets a chance to clean up after itself. SIGTERM asks a process to terminate and lets it run its own shutdown logic, while SIGKILL is an unconditional kernel-level termination that the process cannot intercept or delay. The distinction matters for avoiding data corruption, leaked resources, and orphaned locks during shutdown. ...

August 2, 2026 · 3 min · 463 words · jeonck

Blocking vs Non-blocking I/O: How a Thread Waits for Data

Overview Blocking and non-blocking I/O differ in what happens to the calling thread when a read or write can’t complete immediately. Blocking I/O suspends the thread until data is ready; non-blocking I/O returns at once and lets the caller check back later. The choice shapes how a system scales to many simultaneous connections. Comparison Diagram Blocking I/ONon-blocking I/OThreadcall read()thread blockedno other work possibleuntil data arrivesdata ready, resumes1 thread ≈ 1 in-flight callthread / event loopread() returns at oncepoll / epoll checkretrymeanwhile: serves otherconnectionsready → callback fires1 thread ≈ many in-flight calls Comparison Table Aspect Blocking I/O Non-blocking I/O Call behavior Call halts the calling thread until the operation completes Call returns immediately, with data or an EWOULDBLOCK/EAGAIN error Thread state while I/O is pending Thread is suspended off the run queue — no CPU used, but unavailable for other work Thread stays runnable and can be reused to serve other requests How readiness is discovered OS wakes the thread automatically once data is ready Caller polls or registers with select/poll/epoll/kqueue Concurrency model One thread (or process) per concurrent connection Single or few threads multiplex many connections via an event loop Resource overhead at scale Grows linearly with connections — thread stacks, context switches Stays flat, bounded by CPU cores rather than connection count Code / control-flow complexity Simple, sequential, top-to-bottom logic Callback, promise, or async/await structure; state tracked across suspensions Failure / edge-case handling A slow or hung peer blocks the thread indefinitely without a timeout A slow peer only delays its own event; a stalled callback can starve the whole loop Key Differences Blocking I/O ties up a thread for the full call; non-blocking frees it immediately. Non-blocking servers rely on an event loop to learn when data is finally ready. Blocking scales concurrency with more threads; non-blocking scales with more callbacks on fewer threads. Blocking code reads sequentially; non-blocking code needs explicit state management across suspensions. At high connection counts, blocking hits a C10K wall that non-blocking avoids. When to Use Each Blocking I/O ...

August 2, 2026 · 3 min · 488 words · jeonck

Container vs VM: Virtualization Approaches Compared

Overview Containers and virtual machines both let you package and isolate workloads, but they virtualize at different layers of the stack: containers share the host OS kernel while VMs emulate entire hardware and run a full guest OS each. That difference drives everything else — startup speed, image size, isolation strength, and how many instances you can pack onto one host. Comparison Diagram VSContainerVMApp+LibsApp+LibsApp+LibsContainer Engine(Docker / containerd)Host OS Kernel (shared)~MBs · starts in msApp+LibsGuest OSApp+LibsGuest OSApp+LibsGuest OSHypervisor(ESXi / KVM / Hyper-V)Physical Hardware~GBs · starts in minutes Comparison Table Aspect Container VM Isolation boundary OS-level, enforced by kernel namespaces and cgroups Hardware-level, enforced by a hypervisor Guest OS None — shares the host kernel Full guest OS instance per VM Startup time Milliseconds to a few seconds Tens of seconds to minutes (full OS boot) Image/footprint size Megabytes Gigabytes Resource overhead Low; near-native performance Higher; hypervisor plus guest OS overhead Portability Highly portable across any host with a compatible kernel and engine Portable via VM image formats but heavier to move and convert Security isolation strength Weaker — shared kernel widens attack surface Stronger — separate kernel per VM Typical density per host Hundreds of instances Tens of instances Key Differences Containers share the host kernel instead of running a separate OS like VMs. VM isolation is enforced by a hypervisor, giving stronger security boundaries than containers. Containers typically boot in milliseconds, while VMs take minutes to boot a full OS. Container images measure in megabytes; VM images measure in gigabytes. A single host can run far higher density of containers than VMs due to lower per-instance overhead. When to Use Each Container ...

August 2, 2026 · 3 min · 469 words · jeonck

Declarative vs Imperative IaC: Describing the End State vs Scripting the Steps

Overview Declarative IaC (e.g. Terraform, CloudFormation) has you specify the desired end state of infrastructure and lets an engine figure out how to get there. Imperative IaC (e.g. shell scripts, Chef recipes, raw CLI calls) has you write the exact sequence of commands to execute. The distinction matters because it determines who — you or the tool — is responsible for ordering, idempotency, and reconciling drift. Comparison Diagram DeclarativeDesired State"3 servers, 1 LB"Engine Computes Diffplan + dependency graphInfrastructureconverges to match stateEngine decides how & in what orderImperativeStep 1: Create VPCStep 2: Launch ServersStep 3: Attach LBInfrastructureAuthor decides exact steps & order Comparison Table Aspect Declarative Imperative Authoring model Write a desired-state spec Write an ordered command list Execution engine Resolves a dependency graph Runs a sequential interpreter State tracking Maintains a state file Stateless execution Applying changes Single apply command Run the script/playbook Ordering & dependencies Auto-resolved by engine Manually sequenced by author Idempotency Guaranteed by design Developer-enforced Drift detection Built-in plan diff Not built-in Failure handling Partial apply, replan Manual rollback Key Differences Declarative code answers ‘what’, imperative code answers ‘how’. Declarative tools rely on a state file to know current vs. desired infrastructure; imperative scripts have no memory of prior runs. Idempotent re-runs are automatic in declarative tools but must be hand-coded (checks, conditionals) in imperative scripts. Declarative engines build a dependency graph to order operations; imperative code hardcodes that order line by line. Drift correction in declarative IaC is a matter of re-running plan/apply; imperative approaches require re-running or rewriting the exact script. When to Use Each Declarative ...

August 2, 2026 · 2 min · 420 words · jeonck

Monitoring vs Observability: Knowing Something's Wrong vs Knowing Why

Overview Monitoring watches a predefined set of metrics, logs, and checks against known failure modes and alerts you when thresholds are breached. Observability is a property of a system built so that its internal state can be inferred from its external outputs, letting you investigate questions you didn’t think to ask in advance. The distinction matters because monitoring answers ‘is something wrong?’ while observability answers ‘why is it wrong?’ for failures you’ve never seen before. ...

August 2, 2026 · 3 min · 553 words · jeonck