<?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: Brendan Akudo</title>
    <description>The latest articles on DEV Community by Brendan Akudo (@brendan_akudo_voldie).</description>
    <link>https://dev.to/brendan_akudo_voldie</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%2F2285074%2Fb2294e5c-d223-441c-8afa-2362610e0c9d.png</url>
      <title>DEV Community: Brendan Akudo</title>
      <link>https://dev.to/brendan_akudo_voldie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brendan_akudo_voldie"/>
    <language>en</language>
    <item>
      <title>Someone Is Trying to Teach AI to Lie, and It's Weirdly Subtle How They're Doing It</title>
      <dc:creator>Brendan Akudo</dc:creator>
      <pubDate>Tue, 28 Jul 2026 18:32:15 +0000</pubDate>
      <link>https://dev.to/brendan_akudo_voldie/someone-is-trying-to-teach-ai-to-lie-and-its-weirdly-subtle-how-theyre-doing-it-14nf</link>
      <guid>https://dev.to/brendan_akudo_voldie/someone-is-trying-to-teach-ai-to-lie-and-its-weirdly-subtle-how-theyre-doing-it-14nf</guid>
      <description>&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%2Fgqjfsqs1xtg93xqgol8r.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%2Fgqjfsqs1xtg93xqgol8r.webp" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You would expect a mass poisoning of global AI models to involve something as dramatic as agents in dark hoodies and zero-day exploits in some kind of dramatic action thriller.&lt;/p&gt;

&lt;p&gt;Nope. It's just a content factory.&lt;/p&gt;

&lt;p&gt;Welcome to the bizarre, low-budget, but effective world of 'LLM grooming' and the network of websites allegedly behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pravda Network
&lt;/h2&gt;

&lt;p&gt;In the French news security group Viginum's telling, it began in February 2024, when they uncovered something of interest: a network of about 150 news outlets, distributing pro-Kremlin content while masquerading as international news sites. The group dubbed the network Portal Kombat, but it has since been alternatively referred to as the Pravda network - a Russian communist-era paper, supposedly a nod to its ideological leanings.&lt;/p&gt;

&lt;p&gt;The first sign that there was something wrong with this network was that almost no one was visiting these sites. Researchers at the American Sunlight Project have dug into this network's numbers and, as explained in one of their reports, found that it generates 3 million articles per year in dozens of languages and with almost no traffic or social media engagement.&lt;/p&gt;

&lt;p&gt;Furthermore, almost none of this content is truly unique - the network redistributes articles from Russian state media and pro-Kremlin forums across its large domain front. So what gives? Who are these articles for?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Audience Isn't People (as you might have guessed lol)
&lt;/h2&gt;

&lt;p&gt;You may have caught the implication in the title by now - the most plausible explanation for the Pravda network's existence is that it is designed to be used against search engines and AI language models.&lt;/p&gt;

&lt;p&gt;Every article is a potential entry into a database, ready to be used by an algorithm that recommends or synthesizes information when asked. By saturating the online space with similar, keyword-rich articles that repeat a certain narrative, a sufficiently large number of them will inevitably be ingested by a model when it queries the web for an answer, or when it trains on a corpus that includes these sites.&lt;/p&gt;

&lt;p&gt;The researchers have a term for this kind of attack - LLM grooming. Essentially, it involves using the sheer prevalence of a certain point of view in the online sphere to bias the opinions of AI assistants or search engines. The theory goes that since an AI model learns to associate factual claims with mentions in news articles, flooding the internet with identical articles containing demonstrably false claims will lead to an AI believing those claims to be true simply because many sources say so.&lt;/p&gt;

&lt;p&gt;According to one American defector, writing in Moscow for a Russian media outlet, that is precisely the goal of the Pravda network - to groom the global opinion space to bend toward the Kremlin's preferred talking points.&lt;/p&gt;

&lt;p&gt;So what gives? Did AI models really get poisoned by this network?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Disinformation Benchmark Is… Sketchy
&lt;/h2&gt;

&lt;p&gt;It depends on who you ask. In the sensationalist narrative, the evidence comes from an audit performed by NewsGuard - a private company that scores news outlets based on their adherence to journalistic standards. They tested ten different chatbots, using ten different false stories attributed to the Pravda network, and found that all of them repeated these claims on about a third of attempts. This figure was immediately weaponized by disinformation skeptics and heavily amplified on social media, but the more cautious responses noted that the measurement methodology was severely flawed.&lt;/p&gt;

&lt;p&gt;In a follow-up piece, several researchers attempted to use similar methods, testing the same set of models but getting much lower figures, closer to 5%. Their criticism of the original benchmark was that two-thirds of the prompts used in the original research had built-in incentives to say "false things," and even when responses were nuanced and did not directly repeat the prompt, they still counted as disinformation. This was similar to asking a respondent "are you SURE you're not a lizard person?" and counting "probably not, but I can't say for sure" as an affirmation of the statement.&lt;/p&gt;

&lt;p&gt;To be sure, both sides of the discussion have valid points. The more technically sound analysis probably leans toward the lower figures - 5–10% - but this is still far from an insignificant level of vulnerability. More importantly, there is a critical difference between the two types of attacks that we see here, and this brings us to the most important finding of all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plot Twist That Makes This Much Less Important Than It Seems (or Not)
&lt;/h2&gt;

&lt;p&gt;There are two ways in which a disinformation campaign can impact a chatbot - and only one of them is particularly difficult to defend against. The first is retrieval-time poisoning - an attack that involves planting false information in search results so that when an AI performs a search, it will ingest this information as credible information.&lt;/p&gt;

&lt;p&gt;This is a nuisance, but the defense against it is relatively simple - one only needs to blocklist the domains known to host disinformation (or, in the case of chatbots, train the models to be skeptical of sources). The other type of poisoning, however, is much more insidious - training-time poisoning, which involves getting false information into a model's training corpus directly.&lt;/p&gt;

&lt;p&gt;This type of attack is much harder to defend against because it requires direct access to the model or its training data. Once false information is embedded in a model's decision-making process, blocklists are ineffective - the model will consistently report "trusted sources" as supporting any desired claim, even when it does not search any such source.&lt;/p&gt;

&lt;p&gt;Until recently, most research suggested that the Pravda network belonged to the first category - a nuisance, not a systemic vulnerability. That changed in 2026, when researchers at the DFRLab discovered Pravda network articles in Common Crawl - a large, widely used database of web content, used as a training ground for many AI models. This was proof that the Pravda network had, indeed, already infiltrated many models - and now, every search performed by one of these models has a higher chance of incorporating disinformation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Should Care
&lt;/h2&gt;

&lt;p&gt;If you are not building a career in the field of large language models, the implications of this discovery might not be immediately obvious to you. There are several practical applications for this information, however, that extend to the wider LLM field. To briefly summarize:&lt;/p&gt;

&lt;p&gt;When designing a retrieval-augmented generation pipeline or another type of LLM-powered search function, always consider the possibility of disinformation in the search results. Blocklists or allowlists for domains associated with disinformation are a must for any such system, and their absence is a severe vulnerability.&lt;/p&gt;

&lt;p&gt;"Lots of sources say it" is not a reliable indication of truth.&lt;/p&gt;

&lt;p&gt;If your system uses a ranking or weighting system that favors sources that are frequently cited, it will be vulnerable to similar attacks. Essentially, any system that treats "quantity of mentions" as a quality metric is susceptible to manipulation - so always consider the source credibility when designing such a system.&lt;/p&gt;

&lt;p&gt;When working with third-party models, remember that their training data may contain disinformation. This means that the same level of verification applies to model outputs as to any other information source - especially when dealing with information that the model has no direct access to.&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%2Fsxemu7q7axfg00x5bkxg.jpg" 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%2Fsxemu7q7axfg00x5bkxg.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Some people only need a dark hoodie and a green screen to mess with our heads - but others only need a low-budget content factory and an understanding of how search engines work. Large language models are a security risk, yes, but rarely in ways one might expect. Disinformation campaigns typically take advantage of weaknesses in the broader system, not unique model-specific vulnerabilities, and the most insidious attacks are often the most bland in execution - millions of low-quality articles, patiently waiting for an unsuspecting crawler to traverse their way to a database.&lt;/p&gt;

&lt;p&gt;Whether this is really a crisis or just an overblown nuisance is up for debate - it very much depends on who you ask. Either way, the implications cut across the entire field of LLM research. Understanding that the internet is a training set means understanding that anyone with access to the internet can potentially bias an AI model. That is unlikely to change anytime soon, and it is a situation that merits awareness no matter what side of the political spectrum one sits on.&lt;/p&gt;

&lt;p&gt;Have you guys heard of LLM poisoning before? If yes, how do you think we can prevent or reduce the impact it has on existing AI models?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources: Viginum, the American Sunlight Project, NewsGuard, EUvsDisinfo, DFRLab, and Al Jazeera.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>disinformation</category>
      <category>llm</category>
      <category>programming</category>
    </item>
    <item>
      <title>Spring Boot for Beginners: The Java Concepts Hiding Under the Hood</title>
      <dc:creator>Brendan Akudo</dc:creator>
      <pubDate>Fri, 24 Jul 2026 13:35:57 +0000</pubDate>
      <link>https://dev.to/brendan_akudo_voldie/spring-boot-for-beginners-the-java-concepts-hiding-under-the-hood-2pjl</link>
      <guid>https://dev.to/brendan_akudo_voldie/spring-boot-for-beginners-the-java-concepts-hiding-under-the-hood-2pjl</guid>
      <description>&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%2F4lft0auznmhtxm9ysgk5.png" 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%2F4lft0auznmhtxm9ysgk5.png" alt=" " width="691" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're learning Java and keep hearing "just use Spring Boot," it can feel like magic. You annotate a class, run one command, and suddenly you have a working REST API with no server setup, no XML config, no boilerplate. That magic isn't magic at all — it's a handful of core Java concepts, wired together cleverly. Once you see them, Spring Boot stops looking mysterious and starts looking like really good engineering.&lt;/p&gt;

&lt;p&gt;This article walks through what Spring Boot actually is, then unpacks the Java fundamentals it leans on: OOP and interfaces, annotations, reflection, generics, and the JVM's packaging model. By the end, you'll understand not just how to use Spring Boot, but why it works.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;What Spring Boot Actually Is&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Spring Boot is a framework built on top of the older Spring Framework. Spring itself solved a real problem: enterprise Java apps in the early 2000s were drowning in XML configuration files just to wire objects together. Spring introduced Dependency Injection and an Inversion of Control (IoC) container to manage that wiring in code instead.&lt;/p&gt;

&lt;p&gt;Spring Boot then solved Spring's own problem: even with DI, configuring a Spring app was still tedious. Boot adds auto-configuration, sensible defaults, and an embedded server, so you can go from zero to a running web app with a single class and a couple of annotations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DemoApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a complete runnable web application. To understand why so little code does so much, we need to look at the Java features underneath it. Let's dive in fellas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Object-Oriented Programming: Classes, Interfaces, Polymorphism&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring is built around plain Java objects. A typical Spring Boot app is layered like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; — handles HTTP requests&lt;br&gt;
&lt;strong&gt;Service&lt;/strong&gt; — holds business logic&lt;br&gt;
&lt;strong&gt;Repository&lt;/strong&gt; — talks to the database&lt;/p&gt;

&lt;p&gt;Each layer is usually defined as an interface with a concrete implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Teddy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why bother with an interface if there's only one implementation? Because Spring depends on Java's polymorphism. Other classes reference &lt;em&gt;UserService&lt;/em&gt;, not &lt;em&gt;UserServiceImpl&lt;/em&gt;. That means you can swap implementations — a mock for testing, a caching decorator, a completely different data source — without touching any code that depends on the interface. This is the Java principle "program to an interface, not an implementation," and Spring is designed around it from top to bottom.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;2. Dependency Injection and Inversion of Control&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;In plain Java, if a class needs a collaborator, it usually creates it itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserServiceImpl&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tightly couples UserController to one specific implementation. Testing it means dragging along the real UserServiceImpl and everything it depends on.&lt;/p&gt;

&lt;p&gt;Spring flips this around. Instead of a class creating its own dependencies, Spring creates the objects for you and hands them over — this is &lt;strong&gt;Dependency Injection (DI)&lt;/strong&gt;. The framework, not your code, decides how objects get wired together — that inversion of responsibility is what "Inversion of Control" means.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You never write new UserServiceImpl() anywhere. At startup, Spring scans your codebase, finds a class annotated @Service that implements UserService, creates an instance of it (a bean), and injects it into UserController's constructor automatically. This single idea — objects declare what they need instead of constructing it — is the backbone of the entire framework, and it's a pattern worth understanding even outside Spring, since it's core to good Java design in general.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;3. Annotations: Metadata That Drives Behavior&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;You've already seen @SpringBootApplication, @Service, and @RestController. Annotations are one of Java's most underrated features: they attach metadata to a class, method, or field without changing its logic.&lt;/p&gt;

&lt;p&gt;On their own, annotations do nothing. @Service doesn't run any code by itself — it's just a marker. It's the framework reading that marker that gives it power. Spring scans your classes at startup, checks which ones carry which annotations, and acts accordingly.&lt;br&gt;
Understanding annotations as "metadata read by a framework" rather than "magic keywords" demystifies most of Spring instantly. The same mechanism powers testing frameworks like JUnit, ORMs like Hibernate, and serialization libraries like Jackson.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;4. Reflection: How Annotations Actually Get Read&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;So how does Spring know, at runtime, which classes have @Service on them, or which fields are marked @Autowired? Through Java's &lt;strong&gt;Reflection API&lt;/strong&gt; — the ability for a running program to inspect its own classes, methods, fields, and annotations.&lt;/p&gt;

&lt;p&gt;A simplified illustration of what Spring is roughly doing internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;clazz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserServiceImpl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clazz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnnotationPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDeclaredConstructor&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;newInstance&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code inspects a class at runtime, checks its annotations, and creates an instance dynamically — all without knowing the exact class name at compile time. Reflection is slower than direct code, which is why Spring does this scanning once at startup and caches the results, rather than repeating it on every request. It's also why a Spring Boot app has a noticeable startup time compared to a bare Java program — that startup cost is the reflection-based wiring happening.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;5. Generics: Type-Safe, Reusable Components&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Spring's data layer leans heavily on generics. Consider the repository interface Spring Data JPA gives you almost for free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it — no implementation required. JpaRepository is a generic interface: User is the entity type, Long is the type of its ID. Generics let Spring provide one reusable, type-checked implementation of common database operations (save, findById, delete, findAll) that works for any entity, without writing separate code for User, Product, or Order. The compiler enforces that you can't accidentally pass a String where an ID Long is expected — type safety, without runtime casting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. POJOs and the JavaBean Convention&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring frequently works with simple data-holder classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a POJO (Plain Old Java Object) following the JavaBean convention: private fields, a no-argument constructor, and public getters/setters. This convention isn't required by the Java language itself — it's a widely followed pattern. Libraries like Jackson (which Spring Boot uses to convert Java objects to JSON and back) rely on reflection to find these getters and setters by name. That's why a field named name needs a method literally named getName() — the library is looking for that exact pattern.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;7. The JVM, JARs, and the Embedded Server&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Traditionally, a Java web app was packaged as a WAR file and deployed onto an external server like Tomcat. Spring Boot changes this: it packages an embedded Tomcat (or Jetty, or Undertow) inside your application, and bundles everything into a single executable JAR.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw clean package
java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/demo-0.0.1-SNAPSHOT.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That JAR contains your compiled classes, all dependencies, and a runnable server, all executed by the JVM with one command. This is possible because of how the JVM loads classes from JAR files at runtime and because build tools like Maven or Gradle handle dependency resolution — pulling in Spring's libraries (and their dependencies) from a repository automatically, based on the pom.xml or build.gradle file you declare.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Putting It Together: A Minimal REST Endpoint&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;With all these pieces in place, a working endpoint is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Walking through what happens when this app starts and a request comes in:&lt;/p&gt;

&lt;p&gt;Spring Boot scans the classpath via reflection, finds classes annotated @Service, @Repository, @RestController, and registers them as beans.&lt;br&gt;
It sees UserController needs a UserService in its constructor and injects the matching bean — DI in action.&lt;br&gt;
The embedded server starts, packaged inside the JAR, no external Tomcat needed.&lt;br&gt;
A GET /api/users/5 request arrives. Spring maps it to getUser, using @GetMapping metadata.&lt;br&gt;
The returned User POJO gets serialized to JSON by Jackson, using reflection to read its getters.&lt;/p&gt;

&lt;p&gt;Every step traces back to a Java fundamental: interfaces, annotations, reflection, generics, or the JVM's classloading model. Spring Boot doesn't replace these concepts — it orchestrates them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Wrapping Up&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring Boot feels like magic mainly because it hides repetitive plumbing behind annotations and sensible defaults. But nothing happening under the hood is exotic — it's core Java, applied consistently and well. Once you can name what's happening at each step — DI, reflection reading annotations, generics giving you type-safe reusable code — the framework becomes predictable instead of mysterious.&lt;/p&gt;

&lt;p&gt;If you're coming from a language without this kind of reflection-and-annotation-driven framework culture, it's worth sitting with these concepts individually before layering Spring on top. They pay off well beyond Spring Boot itself — reflection and annotations show up in testing frameworks, ORMs, and serialization libraries across the Java ecosystem.&lt;/p&gt;

&lt;p&gt;Have you encountered Spring boot and Java before? If yes what was your experience? I'd love feedback from you guys.&lt;br&gt;
Happy Coding ladies and gentlemen.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>LND Explained: A Developer's Intro to Bitcoin's Lightning Network Daemon</title>
      <dc:creator>Brendan Akudo</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:46:23 +0000</pubDate>
      <link>https://dev.to/brendan_akudo_voldie/lnd-explained-a-developers-intro-to-bitcoins-lightning-network-daemon-4gdc</link>
      <guid>https://dev.to/brendan_akudo_voldie/lnd-explained-a-developers-intro-to-bitcoins-lightning-network-daemon-4gdc</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;You've heard of Bitcoin. You've maybe heard of the Lightning Network. But what exactly is LND, and why should developers care? Let's break it down — technically, but from the ground up.&lt;/strong&gt;&lt;/em&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fja5gv69c7rchxkjgx0as.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fja5gv69c7rchxkjgx0as.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem: Bitcoin is Superb but Slow&lt;/strong&gt;&lt;br&gt;
Bitcoin's base layer — the blockchain itself — is intentionally slow. Every transaction must be broadcast to thousands of nodes, verified, and bundled into a block that gets mined roughly &lt;strong&gt;every 10 minutes&lt;/strong&gt;. The network handles about &lt;strong&gt;7 transactions per second&lt;/strong&gt; (TPS).&lt;/p&gt;

&lt;p&gt;Compare that to Visa's ~24,000 TPS and you quickly see the problem. Bitcoin in its raw form isn't built for buying coffee, splitting a bill, or paying a freelancer in real time.&lt;/p&gt;

&lt;p&gt;But there's a solution — and it lives on top of Bitcoin.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Enter the Lightning Network&lt;/strong&gt;&lt;/u&gt;&lt;br&gt;
The Lightning Network is a &lt;strong&gt;Layer 2 (L2) payment protocol&lt;/strong&gt; built on top of Bitcoin. Instead of recording every single payment on the blockchain, it lets two parties open a private payment channel, transact off-chain as many times as they want, and only settle the final balance on-chain when they're done.&lt;/p&gt;

&lt;p&gt;Think of it like running a tab at a bar:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Opening the tab = one blockchain transaction&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Each round of drinks = instant off-chain payment&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Closing the tab = one final blockchain transaction&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The result? &lt;strong&gt;Near-instant payments, near-zero fees, and massive throughput&lt;/strong&gt; — without sacrificing Bitcoin's security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;What is LND&lt;/u&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LND stands for Lightning Network Daemon. It's the most widely used implementation of the Lightning Network protocol, built and maintained by Lightning Labs.&lt;/p&gt;

&lt;p&gt;Key facts for developers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Written in Go 🐹&lt;/li&gt;
&lt;li&gt;Exposes a &lt;strong&gt;gRPC API&lt;/strong&gt; (port 10009) and a &lt;strong&gt;REST API&lt;/strong&gt; (port 8080)&lt;/li&gt;
&lt;li&gt;Controlled via a CLI called lncli&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;macaroons&lt;/strong&gt; for authentication (think JWT, but for Lightning)&lt;/li&gt;
&lt;li&gt;Connects to a Bitcoin node (bitcoind or btcd) as its source of truth&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Other Lightning implementations exist — like Core Lightning (CLN) and Eclair — but LND has the largest developer ecosystem and is the best entry point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How LND Fits Into the Stack&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the architecture at a glance:&lt;/p&gt;

&lt;p&gt;Your App / Bot / Service&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
   LND (port 8080 / 10009)   ← you talk to this&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
  Bitcoin Node (bitcoind)     ← watches the blockchain&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
   Bitcoin Network            ← the real blockchain&lt;/p&gt;

&lt;p&gt;LND handles all the Lightning-specific logic: managing channels, routing payments, generating invoices, and keeping track of your node's state. Your application talks to LND through its API and never needs to interact with raw Bitcoin directly.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Core Concepts You Need to Know&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🟠 Your Node&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you run LND, you become a node on the Lightning Network. Your node has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A public key (your identity on the network)&lt;/li&gt;
&lt;li&gt;A wallet (holds on-chain Bitcoin for opening/closing channels)&lt;/li&gt;
&lt;li&gt;A set of channels (your active payment connections)
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
lncli getinfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This prints your node's public key, alias, active channels, and whether it's synced to the chain.&lt;/p&gt;



&lt;p&gt;🔗 &lt;strong&gt;&lt;u&gt;Payment Channels&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A payment channel is a direct financial connection between two Lightning nodes, backed by Bitcoin locked in a multisig address on-chain.&lt;/p&gt;

&lt;p&gt;When you open a channel with someone:&lt;/p&gt;

&lt;p&gt;You commit some Bitcoin into a shared on-chain address (the channel capacity)&lt;br&gt;
The funds are split between local balance (yours) and remote balance (theirs)&lt;br&gt;
You can now send payments instantly without touching the blockchain&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Open a channel with another node&lt;/span&gt;
lncli openchannel &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;their_pubkey&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--local_amt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;500000     &lt;span class="c"&gt;# satoshis (0.005 BTC)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Channels are bidirectional — once open, both parties can send and receive, as long as they have balance on their side.&lt;/p&gt;




&lt;p&gt;⚡ &lt;strong&gt;&lt;u&gt;Invoices&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Lightning, the receiver creates an invoice — a payment request that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The amount (in satoshis)&lt;/li&gt;
&lt;li&gt;A payment hash (for verification)&lt;/li&gt;
&lt;li&gt;An expiry time&lt;/li&gt;
&lt;li&gt;Routing hints
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create an invoice for 1000 satoshis&lt;/span&gt;
lncli addinvoice &lt;span class="nt"&gt;--amt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000 &lt;span class="nt"&gt;--memo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Coffee payment"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns a &lt;em&gt;payment_request&lt;/em&gt; string that starts with lnbc... — this is what the sender uses to pay you.&lt;/p&gt;




&lt;p&gt;🔀 Routing (HTLCs)&lt;/p&gt;

&lt;p&gt;What if you want to pay someone you don't have a direct channel with? That's where routing comes in.&lt;/p&gt;

&lt;p&gt;Lightning routes payments through intermediate nodes using a cryptographic trick called HTLC — Hashed Timelock Contract. Here's the simplified version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sender generates a random secret and hashes it → payment_hash&lt;/li&gt;
&lt;li&gt;Payment hops across nodes: each node locks funds saying "I'll release this if I get the preimage (secret) within X blocks"&lt;/li&gt;
&lt;li&gt;The receiver reveals the secret, unlocking funds hop by hop back to the sender&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The beauty: no node in the middle can steal funds. They either forward correctly and earn a tiny fee, or the payment fails and everything is refunded. Zero trust required.&lt;/p&gt;




&lt;p&gt;🍪 Macaroons (Auth)&lt;/p&gt;

&lt;p&gt;LND uses macaroons for API authentication — a token-based system with built-in caveats. Think of them as JWTs with access scoping baked in.&lt;/p&gt;

&lt;p&gt;There are three default macaroons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;- admin.macaroon - full access(read + write)&lt;/li&gt;
&lt;li&gt;- readonly.macaroon - Read-only&lt;/li&gt;
&lt;li&gt;- invoice.macaroon - Create/manage invoices only&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You pass these in API headers or via lncli when connecting to a remote node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lncli &lt;span class="nt"&gt;--macaroonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/admin.macaroon getinfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scoping matters for production ie your public facing app should only ever get the invoice.macaroon, not the admin one.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;u&gt;Talking to LND via REST API&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're building an app you'll likely call LND's REST API directly. Here's a minimal example in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/tls"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/hex"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NodeInfo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Alias&lt;/span&gt;             &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"alias"`&lt;/span&gt;
    &lt;span class="n"&gt;NumActiveChannels&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"num_active_channels"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Read and hex-encode the macaroon&lt;/span&gt;
    &lt;span class="n"&gt;macBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin.macaroon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;macaroon&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;macBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Skip TLS verification for local dev (don't do this in prod!)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;TLSClientConfig&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;InsecureSkipVerify&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"https://localhost:8080/v1/getinfo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Grpc-Metadata-macaroon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macaroon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="n"&gt;NodeInfo&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Node alias: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Active channels: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumActiveChannels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Going Deeper: gRPC with Go&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;REST is great for quick integrations, but for production apps the gRPC interface is faster and type-safe. Since LND is written in Go, the integration is very clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/lightningnetwork/lnd/lnrpc"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
    &lt;span class="s"&gt;"google.golang.org/grpc/credentials"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Load TLS cert&lt;/span&gt;
    &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClientTLSFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tls.cert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:10009"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTransportCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lnrpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewLightningClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Don't forget to attach your macaroon in production!&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lnrpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetInfoRequest&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Node: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Channels: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumActiveChannels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;&lt;u&gt;Common Gotchas for Developers&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🔴 &lt;em&gt;"Channels need confirmations"&lt;/em&gt; — Opening a channel requires your funding transaction to be confirmed on-chain (usually 3–6 blocks). On regtest, you mine these manually. On testnet, just wait a few minutes.&lt;/p&gt;

&lt;p&gt;🔴 &lt;em&gt;"Insufficient local balance"&lt;/em&gt; — You can only send what's on your local side of a channel. If your local balance is 0, you need inbound liquidity from the other side.&lt;/p&gt;

&lt;p&gt;🔴 &lt;em&gt;"LND won't start without a synced bitcoind"&lt;/em&gt; — LND depends on a running, synced Bitcoin node. Make sure bitcoind is running and accessible before starting LND.&lt;/p&gt;

&lt;p&gt;🔴 &lt;em&gt;"TLS errors in Codespaces / remote environments"&lt;/em&gt; — LND's TLS cert is generated for localhost. When running remotely (like in GitHub Codespaces), you may need to regenerate the cert with the right --tlsextraip or --tlsextradomain flags, or use the REST API with TLS verification disabled for local dev.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;u&gt;What Can You Build on LND?&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you have LND running, the possibilities are wide:&lt;/p&gt;

&lt;p&gt;💸 Payment processors — Accept Bitcoin Lightning payments in your app&lt;br&gt;
🤖 Bots — Tip bots for Telegram, Twitter, Discord&lt;br&gt;
🏦 Savings &amp;amp; treasury apps — Group wallets, savings pools (think chamas!)&lt;br&gt;
🎮 Micropayment games — Pay-per-action gaming mechanics&lt;br&gt;
📡 Streaming payments — Pay-per-second for APIs, content, bandwidth&lt;br&gt;
🔐 Multiparty wallets — Shared custody with multi-signature channels&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Final words...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LND transforms Bitcoin from a slow settlement layer into a real-time programmable payment rail. As a developer, you get a clean API, a mature CLI, and a rich ecosystem of libraries — all built on top of the most secure monetary network on the planet.&lt;/p&gt;

&lt;p&gt;The mental model is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect to a Bitcoin node&lt;/li&gt;
&lt;li&gt;Fund your on-chain wallet&lt;/li&gt;
&lt;li&gt;Open payment channels with peers&lt;/li&gt;
&lt;li&gt;Send and receive instant off-chain payments&lt;/li&gt;
&lt;li&gt;Settle on-chain whenever you're done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once that clicks, you can start building real apps — savings pools, micropayment APIs, group treasuries — on rails that are already live and working worldwide.&lt;/p&gt;

&lt;p&gt;Happy building ladies and gentlemen. &lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'd like to know if and how you learned about LND, have you incorporated it in any of your systems? What would you improve about it?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>bitcoin</category>
      <category>blockchain</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Stop Fearing the Blinking Cursor: Overcoming Terminal Anxiety</title>
      <dc:creator>Brendan Akudo</dc:creator>
      <pubDate>Tue, 02 Jun 2026 07:36:07 +0000</pubDate>
      <link>https://dev.to/brendan_akudo_voldie/stop-fearing-the-blinking-cursor-overcoming-terminal-anxiety-4d9</link>
      <guid>https://dev.to/brendan_akudo_voldie/stop-fearing-the-blinking-cursor-overcoming-terminal-anxiety-4d9</guid>
      <description>&lt;p&gt;The first time I opened a terminal, I stared at it for a solid minute.&lt;/p&gt;

&lt;p&gt;No buttons. No menus. No helpful icons.&lt;/p&gt;

&lt;p&gt;Just a black screen and a blinking cursor that seemed to be asking, &lt;em&gt;"Well? What are you waiting for?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you've ever felt intimidated by the command line, you're not alone. The terminal has an unfair reputation. Movies portray it as a mysterious tool used by elite hackers, while online forums are full of stories about people accidentally deleting important files with a single command.&lt;/p&gt;

&lt;p&gt;It's enough to make any beginner nervous.&lt;/p&gt;

&lt;p&gt;The most common fear is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What if I type the wrong thing and break my computer?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The good news is that the terminal is far less dangerous than most people think. In reality, it's not a weapon waiting to be misused—it's a conversation between you and your operating system.&lt;/p&gt;

&lt;p&gt;Like any conversation, once you learn a few basic words, everything starts to make sense.&lt;/p&gt;

&lt;p&gt;In this article, we'll strip away the mystery and focus on a handful of beginner-friendly commands that help you navigate your system confidently. By the end, you'll understand how to move around, find your way back when you're lost, and—most importantly—stop being afraid of that blinking cursor.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Myth of the "Self-Destruct Button"
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Fear
&lt;/h3&gt;

&lt;p&gt;"I'm going to destroy my computer by typing the wrong thing."&lt;/p&gt;

&lt;p&gt;It's a reasonable concern. The terminal looks powerful because it is powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Reality
&lt;/h3&gt;

&lt;p&gt;Your operating system has safeguards in place. Most potentially dangerous actions require elevated privileges, often through commands such as &lt;code&gt;sudo&lt;/code&gt;, which stands for &lt;strong&gt;SuperUser Do&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without those permissions, your computer actively prevents many system-level changes.&lt;/p&gt;

&lt;p&gt;For beginners learning navigation commands, you're essentially exploring in a safe environment. You're looking around, not rewiring the house.&lt;/p&gt;




&lt;h2&gt;
  
  
  Think of the Terminal as Read-Only Exploration
&lt;/h2&gt;

&lt;p&gt;Before changing anything, let's learn how to &lt;em&gt;look around&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These commands are completely safe because they only display information.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;pwd&lt;/code&gt; — Where Am I?
&lt;/h3&gt;

&lt;p&gt;Think of &lt;code&gt;pwd&lt;/code&gt; as your GPS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/home/brendan/projects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It simply tells you your current location in the filesystem.&lt;/p&gt;

&lt;p&gt;No files are modified.&lt;br&gt;
Nothing is deleted.&lt;br&gt;
Zero risk.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;ls&lt;/code&gt; — What's Here?
&lt;/h3&gt;

&lt;p&gt;Think of &lt;code&gt;ls&lt;/code&gt; as opening your eyes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Documents Downloads Pictures projects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It lists the contents of your current directory.&lt;/p&gt;

&lt;p&gt;Again, nothing changes. You're simply observing.&lt;/p&gt;

&lt;p&gt;When I was learning the terminal, I probably ran &lt;code&gt;ls&lt;/code&gt; hundreds of times because I was constantly checking where I was and what was around me.&lt;/p&gt;

&lt;p&gt;That's completely normal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Taking Control: Moving Around
&lt;/h2&gt;

&lt;p&gt;Once you know where you are, it's time to move.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;cd&lt;/code&gt; — Change Directory
&lt;/h3&gt;

&lt;p&gt;Imagine clicking through several folders in a graphical file manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Documents → Projects → Portfolio → Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the terminal, you can jump there instantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Documents/Projects/Portfolio/Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No clicking required.&lt;/p&gt;

&lt;p&gt;The more projects you work on, the more you'll appreciate how much faster this becomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;cd ..&lt;/code&gt; — The Universal Undo
&lt;/h3&gt;

&lt;p&gt;Made a wrong turn?&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This moves you back one directory level.&lt;/p&gt;

&lt;p&gt;Think of it as the terminal equivalent of saying:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Actually, take me back."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's one of the most useful commands you'll ever learn.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Do When You Get Stuck
&lt;/h2&gt;

&lt;p&gt;Every beginner eventually runs into a moment where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A command won't stop running.&lt;/li&gt;
&lt;li&gt;The screen fills with text.&lt;/li&gt;
&lt;li&gt;Something looks confusing.&lt;/li&gt;
&lt;li&gt;Panic starts creeping in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fortunately, the terminal comes with built-in escape hatches.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Ctrl + C&lt;/code&gt; — Emergency Stop
&lt;/h3&gt;

&lt;p&gt;If a command seems stuck, press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl + C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the terminal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stop whatever you're doing and give me my cursor back.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Learning this shortcut instantly made me more confident because I realized I wasn't trapped if I made a mistake.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;clear&lt;/code&gt; (or &lt;code&gt;Ctrl + L&lt;/code&gt;) — Start Fresh
&lt;/h3&gt;

&lt;p&gt;When your screen becomes cluttered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl + L
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The terminal clears the screen and gives you a clean workspace.&lt;/p&gt;

&lt;p&gt;Sometimes the best debugging technique is simply removing the visual chaos and starting again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The terminal isn't scary because it's dangerous.&lt;/p&gt;

&lt;p&gt;It's scary because it's unfamiliar.&lt;/p&gt;

&lt;p&gt;Every developer, system administrator, DevOps engineer, and cybersecurity professional started exactly where you are now: staring at a blinking cursor and wondering what to type next.&lt;/p&gt;

&lt;p&gt;The secret isn't knowing hundreds of commands.&lt;/p&gt;

&lt;p&gt;It's knowing a few basic ones well enough to explore confidently.&lt;/p&gt;

&lt;p&gt;Start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd ..&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clear&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember your panic button:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl + C&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you master these, that blinking cursor stops looking intimidating and starts looking like an invitation.&lt;/p&gt;




&lt;p&gt;Do you remember your first experience with the command line? What surprised you the most?&lt;/p&gt;

</description>
      <category>cli</category>
      <category>terminal</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>cat: What It Is, What It Does, and Why It does it Matter</title>
      <dc:creator>Brendan Akudo</dc:creator>
      <pubDate>Tue, 19 May 2026 06:15:39 +0000</pubDate>
      <link>https://dev.to/brendan_akudo_voldie/cat-what-it-is-what-it-does-and-why-it-does-it-matter-4e73</link>
      <guid>https://dev.to/brendan_akudo_voldie/cat-what-it-is-what-it-does-and-why-it-does-it-matter-4e73</guid>
      <description>&lt;p&gt;What is cat?&lt;/p&gt;

&lt;p&gt;If you have spent any time in a terminal, you have typed it. Short for concatenate, cat is a fundamental command-line utility that reads files and streams their contents to standard output. It is simple, ubiquitous, and perfectly encapsulates the core Unix ethos: do one thing, and do it well.&lt;br&gt;
The History: Ken Thompson and Unix v1&lt;/p&gt;

&lt;p&gt;Born in 1971 at Bell Labs, cat was authored by Ken Thompson as one of the foundational tools for the first edition of Unix. Its original design was straightforward: accept multiple files, stitch them together sequentially, and dump the output to the screen or redirect it to a new file.&lt;br&gt;
&lt;em&gt;cat file1.txt file2.txt &amp;gt; combined.txt&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Initially written in assembly to squeeze performance out of hardware with just 8K of memory, it was quickly rewritten in C by Dennis Ritchie. This milestone was one of the first proof-of-concept projects validating C as a viable systems language. The Evolution: GNU and BSD Lineages. As modern computing branched out, so did cat. In the 1980s, the Free Software Foundation rebuilt it as part of the GNU coreutils suite. This iteration grew a variety of formatting flags designed to expose hidden file details.&lt;/p&gt;

&lt;p&gt;Concurrently, the Berkeley Software Distribution (BSD) ecosystem created a streamlined variant. This version persists today as the silent, minimalist implementation that is natively shipped with macOS.&lt;br&gt;
Philosophical Debates: "cat -v Considered Harmful."&lt;/p&gt;

&lt;p&gt;The inclusion of flags sparked an early ideological rift. Computer scientist Rob Pike famously critiqued the GNU additions in his essay "UNIX Style, or cat -v Considered Harmful". He argued that bloating fundamental utilities violated the core philosophy of composability: if you need to inspect non-printing characters, you should pipe output to a specialized inspection tool, keeping cat perfectly lightweight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical, Essential Workflows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond standard reading, cat handles complex utilities cleanly when combined with shell native operators:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Multi-file compilation: Use basic redirection to quickly combine continuous notes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;cat intro.md body.md conclusion.md &amp;gt; manuscript.md&lt;/em&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>terminal</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
