<?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: Fabio Hiroki</title>
    <description>The latest articles on DEV Community by Fabio Hiroki (@fabiothiroki).</description>
    <link>https://dev.to/fabiothiroki</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F174933%2F7d19e4d4-a665-4b0c-a04e-9ccc10f21c37.jpg</url>
      <title>DEV Community: Fabio Hiroki</title>
      <link>https://dev.to/fabiothiroki</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fabiothiroki"/>
    <language>en</language>
    <item>
      <title>Chat With Your Database for Free: Build a Private AI Agent in Python</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Sat, 27 Dec 2025 13:54:16 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/chat-with-your-database-for-free-build-a-private-ai-agent-in-python-j80</link>
      <guid>https://dev.to/fabiothiroki/chat-with-your-database-for-free-build-a-private-ai-agent-in-python-j80</guid>
      <description>&lt;p&gt;You know the scenario. You are deep in flow state, solving a complex backend problem, when a Slack notification pops up from a Product Manager:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Hey, can you quickly pull a list of all users who signed up in Germany last week? I need it for a meeting in 10 minutes.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You know SQL. You could write that query in your sleep. &lt;strong&gt;But you shouldn’t have to.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every minute you spend writing ad-hoc reporting queries is a minute stolen from building actual product features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution is not to build another complex Admin Dashboard&lt;/strong&gt;. The solution is to give your team a tool that speaks their language.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a &lt;strong&gt;“Chat with your Database”&lt;/strong&gt; application. It allows non-technical users to ask questions in plain English, while an AI writes and executes the safe, read-only SQL under the hood.&lt;/p&gt;

&lt;p&gt;Best of all? It can run &lt;strong&gt;100% locally&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No API Keys:&lt;/strong&gt; It costs $0.00.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Data Privacy Risks:&lt;/strong&gt; Your production schema never goes to OpenAI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No “Glue Code” Nightmares&lt;/strong&gt;: We will use the new &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; to keep the architecture clean.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of this guide, you will have a deployable Docker container that turns “Hey, can you pull this data?” into “Sure, just ask the bot.”&lt;/p&gt;

&lt;p&gt;Let’s reclaim your time.&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%2Fpoaj5pt03g8f0mc30h53.gif" 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%2Fpoaj5pt03g8f0mc30h53.gif" alt="The actual tool we are building today. No cloud, no API keys, running locally on a MacBook." width="372" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Blueprint
&lt;/h2&gt;

&lt;p&gt;To keep this tutorial digestible, I will focus on the &lt;strong&gt;core logic&lt;/strong&gt; of the AI integration. I won’t bore you with 50 lines of Python import statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can grab the complete code (including the Docker setup and Seed Data generator) here:&lt;br&gt;
👉 &lt;a href="//github.com/fabiothiroki/mcp-local-analyst"&gt;github.com/fabiothiroki/mcp-local-analyst&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clone it, run &lt;code&gt;docker-compose up&lt;/code&gt;, and follow along.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Architecture: “The USB-C for AI”
&lt;/h2&gt;

&lt;p&gt;Before we write a single line of code, we need to understand &lt;em&gt;why&lt;/em&gt; we are using the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the early days of LLMs, connecting a model to a database meant writing messy “glue code.” You had to manually inject table definitions into prompts, parse messy regex to find SQL, and handle every error edge-case yourself. It was brittle and hard to maintain.&lt;/p&gt;

&lt;p&gt;MCP solves this by standardizing the connection. Think of it like a USB-C port for AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources (Context)&lt;/strong&gt;: The AI asks, “What data do I have?” Your server replies with the database schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools (Action)&lt;/strong&gt;: The AI decides, “I need to run a query.” Your server executes the function safely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are decoupling the &lt;strong&gt;Brain&lt;/strong&gt; (the LLM) from the &lt;strong&gt;Hands&lt;/strong&gt; (the Database execution).&lt;/p&gt;

&lt;p&gt;Here is the stack we will build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Brain: Mistral 7B&lt;/strong&gt; running on &lt;strong&gt;Ollama&lt;/strong&gt;. (We chose Mistral because it follows strict JSON instructions better than many larger models).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Interface&lt;/strong&gt;: A &lt;strong&gt;Streamlit&lt;/strong&gt; app where the user chats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Server&lt;/strong&gt;: A &lt;strong&gt;Python&lt;/strong&gt; script using FastMCP that holds the SQLite connection.&lt;/li&gt;
&lt;/ul&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%2Futop7v38iqbwk8vql620.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%2Futop7v38iqbwk8vql620.png" alt="A chatbot receiving data questions" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: The Environment (Docker is Your Friend)
&lt;/h2&gt;

&lt;p&gt;We will use Docker to avoid “it works on my machine” syndrome. We need a container that holds our UI and our Database, but can still talk to the Ollama instance running on your host machine.&lt;br&gt;
Become a member&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file. This is your “one-click” setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mcp-reporter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pocket_analyst&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8501:8501"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data:/app/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Crucial: This lets the container talk to Ollama on your laptop&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;OLLAMA_HOST=http://host.docker.internal:11434&lt;/span&gt;
    &lt;span class="na"&gt;extra_hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host.docker.internal:host-gateway"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: The Server (Giving the AI “Hands”)
&lt;/h2&gt;

&lt;p&gt;We use the &lt;em&gt;FastMCP&lt;/em&gt; library to create a server. This script does two things: exposes the database schema (Context) and provides a function to query it (Tool).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I’ve omitted code for brevity. Check &lt;code&gt;src/server.py&lt;/code&gt; in the repo for the full context.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ... standard imports and DB setup (see repo) ...
&lt;/span&gt;
&lt;span class="nd"&gt;@mcp.resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqlite://schema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Reads the database schema and returns it as context.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# In a real app, you would query sqlite_master dynamically
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CREATE TABLE transactions...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@mcp.tool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Executes a read-only SQL query against the database.
    Args:
        sql: The SELECT statement to execute.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Connect to the database and execute the query (see repo)
&lt;/span&gt;
    &lt;span class="c1"&gt;# Return results as clean JSON dictionaries
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: The Brain (Why Mistral Wins)
&lt;/h2&gt;

&lt;p&gt;Now we need the “Host” — the Streamlit app that manages the conversation.&lt;/p&gt;

&lt;p&gt;We are using &lt;strong&gt;Ollama&lt;/strong&gt; to run the model. But here is a critical insight from my testing: &lt;strong&gt;Use Mistral 7B, not Llama 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While Llama 3 is powerful, smaller models often struggle with strict JSON formatting. You ask for &lt;code&gt;{ “sql”: “…” }&lt;/code&gt; and Llama might reply with &lt;em&gt;“Sure! Here is your JSON: { … }”&lt;/em&gt;. That extra conversational text breaks your parser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistral 7B&lt;/strong&gt; is remarkably disciplined. It shuts up and outputs the JSON we need to trigger our tool.&lt;/p&gt;

&lt;p&gt;Here is the logic for &lt;code&gt;src/app.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ... imports and Streamlit page config omitted ...
&lt;/span&gt;
&lt;span class="c1"&gt;# The System Prompt is where we "program" the behavior
# We explicitly tell the model about the schema and the output format
&lt;/span&gt;&lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are a Data Analyst. 
1. Output ONLY a JSON object with the tool call.
2. The format must be: { &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; }
3. Always convert cents to main currency units in the final answer.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# ... inside the main chat loop ...
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask a question...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Send the user's request to Ollama
&lt;/span&gt;    &lt;span class="c1"&gt;# Note: We use format='json' to force structured output
&lt;/span&gt;    &lt;span class="n"&gt;response&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="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mistral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; 
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Parse the tool call
&lt;/span&gt;    &lt;span class="c1"&gt;# (Full error handling and JSON parsing logic is in the repo)
&lt;/span&gt;    &lt;span class="n"&gt;tool_call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&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;tool_call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query_database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# 3. Execute the SQL via our MCP Server
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_mcp_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sql&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# 4. Feed the data back to Mistral to summarize
&lt;/span&gt;        &lt;span class="n"&gt;final_answer&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="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mistral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[...,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&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;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_answer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&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;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%2Fq34nh4xg1rnkboh123ba.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%2Fq34nh4xg1rnkboh123ba.png" alt="Python and Mistral logos in a computer screen" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Talking to Your Data
&lt;/h2&gt;

&lt;p&gt;Once you run &lt;code&gt;docker-compose up&lt;/code&gt;, your container spins up. It automatically runs a &lt;code&gt;seed_data.py&lt;/code&gt; script (included in the repo) that fills your SQLite database with 2,000 realistic “Mock Stripe” transactions.&lt;/p&gt;

&lt;p&gt;Now, let’s see why this is better than a static dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 1: The “Complex Filter”
&lt;/h3&gt;

&lt;p&gt;In a traditional dashboard, if you wanted to see “Failed payments from Germany,” you’d need a filter for Status and a filter for Country.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;How many failed credit card payments did we receive from Germany yesterday?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Logic:&lt;/strong&gt;&lt;br&gt;
Mistral analyzes the schema. It sees &lt;em&gt;country_code&lt;/em&gt;, &lt;em&gt;status&lt;/em&gt;, &lt;em&gt;payment_method&lt;/em&gt;, and &lt;em&gt;created_at&lt;/em&gt;. It generates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;country_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'DE'&lt;/span&gt; 
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt; 
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;payment_method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'card'&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'now'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-1 day'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test 2: The “Ad-Hoc Transformation”
&lt;/h3&gt;

&lt;p&gt;This is the killer feature. Product Managers often want data formatted in a specific way for their own reports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Calculate the total EUR payments per country in the last month, format in CSV&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;br&gt;
The MCP tool returns raw JSON. The LLM then takes that JSON and re-writes it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Country Code","Total EUR Payments"
"US",2873932
"DE",1093878
"GB",533471
"BR",492770
"FR",454523
"JP",348649
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fatal flaw of traditional dashboards is that they only answer the questions you predicted users would ask; this architecture solves the problems you never saw coming, replacing a finite set of hard-coded buttons with the infinite flexibility of language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s keep growing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Subscribe to level up your engineering career with confidence.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The “Traffic Jam” That Kills Your Database (And How to Fix It)</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Mon, 22 Dec 2025 07:54:47 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/the-traffic-jam-that-kills-your-database-and-how-to-fix-it-5gdd</link>
      <guid>https://dev.to/fabiothiroki/the-traffic-jam-that-kills-your-database-and-how-to-fix-it-5gdd</guid>
      <description>&lt;p&gt;You write a perfect banking API. The logic is sound. The math is flawless. The unit tests pass with green checkmarks every time.&lt;/p&gt;

&lt;p&gt;Then, you launch.&lt;/p&gt;

&lt;p&gt;Traffic spikes. Two users try to send money to each other simultaneously. Suddenly, your logs explode with red text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deadlock detected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The database didn’t crash because of a bug in your math. It crashed because of a bug in your &lt;em&gt;timing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is how deadlocks happen, how to simulate them with Python, and the one-line logic change that fixes them forever.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; You can reproduce this deadlock locally using Docker. Get the full code, including the API and the &lt;code&gt;attack.py&lt;/code&gt; script, here: &lt;a href="https://github.com/fabiothiroki/deadlock-database" rel="noopener noreferrer"&gt;[Link to GitHub Repository]&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The “Mexican Standoff”
&lt;/h2&gt;

&lt;p&gt;A database deadlock is exactly like a standoff in a western movie.&lt;/p&gt;

&lt;p&gt;Imagine two friends, Alice and Bob. They decide to send $10 to each other at the exact same millisecond.&lt;/p&gt;

&lt;p&gt;Here is what happens in the database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction A&lt;/strong&gt; (Alice paying Bob): Locks Alice’s row. It now needs to lock Bob’s row to deposit the money.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction B&lt;/strong&gt; (Bob paying Alice): Locks Bob’s row. It now needs to lock Alice’s row to deposit the money.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Transaction A waits for Bob. Transaction B waits for Alice.&lt;/p&gt;

&lt;p&gt;Neither can move. Neither will quit. They will wait for eternity.&lt;/p&gt;

&lt;p&gt;Fortunately, modern database engines are smart. They see this circle, realize it will never end, and play the role of the referee. The database brutally kills one of the transactions to let the other survive.&lt;/p&gt;

&lt;p&gt;But for your user, that looks like a generic &lt;code&gt;500 Internal Server Error&lt;/code&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%2F8x1dag1si0mquot19vso.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%2F8x1dag1si0mquot19vso.png" alt="A picture simulating a database traffic jam" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Crime Scene (The Unsafe Code)
&lt;/h2&gt;

&lt;p&gt;Let’s look at the Python code that causes this disaster.&lt;/p&gt;

&lt;p&gt;We are using FastAPI and psycopg to talk to our database. In our “unsafe” transfer endpoint, we lock the sender first, then the receiver.&lt;/p&gt;

&lt;p&gt;This feels logical. If I am sending money, I should check my balance first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/transfer/unsafe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transfer_unsafe&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;TransferRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 1. Lock the sender's account
&lt;/span&gt;            &lt;span class="c1"&gt;# We MUST lock here to safely check if they have funds.
&lt;/span&gt;            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT balance FROM accounts WHERE id = %s FOR UPDATE&lt;/span&gt;&lt;span class="sh"&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;from_account&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;current_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&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;current_balance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Insufficient funds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# ARTIFICIAL DELAY (Simulating latency)
&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

            &lt;span class="c1"&gt;# 2. Perform the Transfer
&lt;/span&gt;            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE accounts SET balance = balance - %s WHERE id = %s&lt;/span&gt;&lt;span class="sh"&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;amount&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;from_account&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="c1"&gt;# --- THE TRAP IS HERE ---
&lt;/span&gt;            &lt;span class="c1"&gt;# This UPDATE statement implicitly tries to lock the receiver's row.
&lt;/span&gt;            &lt;span class="c1"&gt;# If Bob is the receiver, and Bob is running a transaction... deadlock.
&lt;/span&gt;            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE accounts SET balance = balance + %s WHERE id = %s&lt;/span&gt;&lt;span class="sh"&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;amount&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;to_account&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="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The critical command here is FOR UPDATE.&lt;/p&gt;

&lt;p&gt;This tells the database: “I am reading this row, but don’t let anyone else touch it until I’m done.”&lt;/p&gt;

&lt;p&gt;If Alice runs this (Locking 1, wanting 2) and Bob runs this (Locking 2, wanting 1) at the same time, the application breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Attack (Proving It)
&lt;/h2&gt;

&lt;p&gt;You should never trust theory until you break it in practice.&lt;br&gt;
Become a member&lt;/p&gt;

&lt;p&gt;I wrote a script, &lt;code&gt;attack.py&lt;/code&gt;, that uses &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; to launch concurrent requests. It forces Alice to pay Bob and Bob to pay Alice simultaneously.&lt;/p&gt;

&lt;p&gt;Here is the result of the attack on the unsafe endpoint:&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="nt"&gt;---&lt;/span&gt; Starting Attack &lt;span class="nt"&gt;---&lt;/span&gt;
Mode: UNSAFE &lt;span class="o"&gt;(&lt;/span&gt;Deadlock prone&lt;span class="o"&gt;)&lt;/span&gt;
Users: 8

&lt;span class="o"&gt;[&lt;/span&gt;1] ✅ Success: Alice -&amp;gt; Bob
&lt;span class="o"&gt;[&lt;/span&gt;3] ❌ DEADLOCK: Bob -&amp;gt; Alice
&lt;span class="o"&gt;[&lt;/span&gt;2] ✅ Success: Alice -&amp;gt; Bob
&lt;span class="o"&gt;[&lt;/span&gt;5] ❌ DEADLOCK: Bob -&amp;gt; Alice
&lt;span class="o"&gt;[&lt;/span&gt;4] ✅ Success: Alice -&amp;gt; Bob
...
Success:   6
Deadlocks: 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database throws a DeadlockDetected error. The transaction is rolled back. The money doesn’t move. The user is angry.&lt;/p&gt;

&lt;p&gt;You cannot fix this with faster hardware.&lt;/p&gt;

&lt;p&gt;You cannot fix this by optimizing your SQL queries.&lt;/p&gt;

&lt;p&gt;You fix this with &lt;strong&gt;Geometry&lt;/strong&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%2F6y2n2dk6k7j9kij3m18s.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%2F6y2n2dk6k7j9kij3m18s.png" alt="A mobile phone showing a baking application" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Lock Ordering
&lt;/h2&gt;

&lt;p&gt;To prevent a cycle, you must ensure that everyone acquires locks in the exact same order.&lt;/p&gt;

&lt;p&gt;It doesn’t matter who is paying whom.&lt;/p&gt;

&lt;p&gt;You must always lock the account with the &lt;strong&gt;smaller ID&lt;/strong&gt; before the account with the &lt;strong&gt;larger ID&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario A&lt;/strong&gt; (Alice pays Bob): Lock ID 1 (Alice), then Lock ID 2 (Bob).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scenario B&lt;/strong&gt; (Bob pays Alice): Lock ID 1 (Alice), then Lock ID 2 (Bob).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the difference? In Scenario B, Bob wants to send money. But our code forces him to lock Alice’s account (ID 1) &lt;em&gt;before&lt;/em&gt; he locks his own account (ID 2).&lt;/p&gt;

&lt;p&gt;If Alice and Bob click “Send” at the same time, they both race to lock ID 1.&lt;/p&gt;

&lt;p&gt;One wins. The other waits.&lt;/p&gt;

&lt;p&gt;The winner finishes, releases the lock, and the loser proceeds. &lt;strong&gt;No circle. No deadlock.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Safe Code
&lt;/h2&gt;

&lt;p&gt;Here is the fix. It is surprisingly simple. We sort the IDs before we touch the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/transfer/safe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transfer_safe&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;TransferRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Determine lock order: Low ID first, High ID second
&lt;/span&gt;    &lt;span class="n"&gt;first_lock_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&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;from_account&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;to_account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;second_lock_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&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;from_account&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;to_account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 1. Lock accounts in a fixed, consistent order
&lt;/span&gt;            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT balance FROM accounts WHERE id = %s FOR UPDATE&lt;/span&gt;&lt;span class="sh"&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;first_lock_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;

            &lt;span class="c1"&gt;# Even with a delay, the second transaction is just WAITING for the first lock.
&lt;/span&gt;            &lt;span class="c1"&gt;# It hasn't locked anything yet, so no deadlock is possible.
&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

            &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT balance FROM accounts WHERE id = %s FOR UPDATE&lt;/span&gt;&lt;span class="sh"&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;second_lock_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;

            &lt;span class="c1"&gt;# 2. Now that we have both locks, we check balances and transfer...
&lt;/span&gt;            &lt;span class="c1"&gt;# (Logic proceeds as normal)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By enforcing a global standard for locking (Lowest -&amp;gt; Highest), we physically prevent the circular dependency that causes the crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Aftermath
&lt;/h2&gt;

&lt;p&gt;I ran the exact same attack.py script against the /transfer/safe endpoint.&lt;/p&gt;

&lt;p&gt;The latency was slightly higher (because processes had to wait in line), but look at the reliability:&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="nt"&gt;---&lt;/span&gt; Starting Attack &lt;span class="nt"&gt;---&lt;/span&gt;
Mode: SAFE &lt;span class="o"&gt;(&lt;/span&gt;Fixed&lt;span class="o"&gt;)&lt;/span&gt;
Users: 8

&lt;span class="o"&gt;[&lt;/span&gt;0] ✅ Success: Bob -&amp;gt; Alice
&lt;span class="o"&gt;[&lt;/span&gt;1] ✅ Success: Alice -&amp;gt; Bob
&lt;span class="o"&gt;[&lt;/span&gt;2] ✅ Success: Bob -&amp;gt; Alice
&lt;span class="o"&gt;[&lt;/span&gt;3] ✅ Success: Alice -&amp;gt; Bob
...
Success:   20
Deadlocks: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero crashes. Perfect consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Deadlocks aren’t random bad luck. They are predictable consequences of inconsistent locking.&lt;/p&gt;

&lt;p&gt;If you touch multiple rows in a single transaction, always touch them in the same order.&lt;/p&gt;

&lt;p&gt;Sort your IDs. Save your database.&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Build a Free, Private “Chat with PDF” App in 70 Lines of Python</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 09 Dec 2025 07:12:25 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/build-a-free-private-chat-with-pdf-app-in-70-lines-of-python-4dn8</link>
      <guid>https://dev.to/fabiothiroki/build-a-free-private-chat-with-pdf-app-in-70-lines-of-python-4dn8</guid>
      <description>&lt;p&gt;You have a private PDF you need to talk to.&lt;/p&gt;

&lt;p&gt;But you can’t just upload it to ChatGPT. It might contain sensitive client data, internal business plans, or personal financial information.&lt;/p&gt;

&lt;p&gt;So you search for a local solution, but every tutorial drags you through a maze of broken dependencies and cryptic error messages. It’s frustrating. It feels like it should be simple.&lt;/p&gt;

&lt;p&gt;This guide is different. It gives you a complete, working setup using free, open-source tools that respect your privacy.&lt;/p&gt;

&lt;p&gt;We’ll use Ollama for the brain, LanceDB for the memory, and a specific set of libraries that are guaranteed to play nicely together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Stack? Privacy, Power, and Zero Cost.
&lt;/h2&gt;

&lt;p&gt;The goal is total control and zero cost.&lt;/p&gt;

&lt;p&gt;This architecture is built on two core components that run entirely on your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; lets you run powerful large language models (like Llama 3 or Mistral) locally. It’s your offline brain. You download it once, and it’s yours to use forever, no internet connection or API key required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lancedb.com/" rel="noopener noreferrer"&gt;LanceDB&lt;/a&gt; is an open-source vector database designed for simplicity and speed. It’s your AI’s long-term memory, storing the knowledge from your documents in a way the model can instantly search. It’s serverless and embeds directly into your Python application.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;Everything happens on your laptop. Your documents are never sent to a third-party server. Your conversations are yours alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Get Your Core Tools Running
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, we need to set up the foundation. This part is surprisingly simple.&lt;/p&gt;

&lt;p&gt;First, download and install Ollama for your operating system (macOS, Windows, or Linux).&lt;/p&gt;

&lt;p&gt;Open a new, separate terminal window and run this command. Leave this terminal running in the background.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: If you get an error that the server is already running, that’s fine: it means the app started automatically.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once installed, open your terminal and pull the models we’ll need. We’ll use Llama 3 for generation and a specialized model for embeddings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull llama3
ollama pull nomic-embed-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. You now have a world-class LLM running on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Secret Sauce: A Dependency List That Just Works
&lt;/h2&gt;

&lt;p&gt;This is where most tutorials fail you.&lt;/p&gt;

&lt;p&gt;They give you code but neglect the most important part: the environment. You end up in “dependency hell,” trying to figure out why libraries refuse to cooperate.&lt;/p&gt;

&lt;p&gt;I’ve done the tedious work for you. For managing Python versions like a pro, I recommend &lt;a href="https://github.com/pyenv/pyenv" rel="noopener noreferrer"&gt;pyenv&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pyenv &lt;span class="nb"&gt;install &lt;/span&gt;3.14.0
pyenv &lt;span class="nb"&gt;local &lt;/span&gt;3.14.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python 3.14.X is the current stable version I built and tested this tutorial.&lt;/p&gt;

&lt;p&gt;Key Libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;lancedb&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.25.3 &lt;span class="nv"&gt;ollama&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.6.1 &lt;span class="nv"&gt;pypdf&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;6.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This specific combination is your shortcut past hours of troubleshooting. It ensures the code runs on the first try.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a quick start, the full repository — including the Python script and requirements.txt — is available on &lt;a href="https://github.com/fabiothiroki/ollama-rag" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s walk through the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: The Code: Your Private RAG Engine in Under 70 Lines
&lt;/h2&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%2Fe8ispcsvrv74ar0rj6dl.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.amazonaws.com%2Fuploads%2Farticles%2Fe8ispcsvrv74ar0rj6dl.webp" alt="Photo by Zulfugar Karimov on Unsplash" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The environment is ready.&lt;/p&gt;

&lt;p&gt;Here is the complete Python script. Make sure to place a PDF file named &lt;code&gt;file.pdf&lt;/code&gt; in the same directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import ollama
import lancedb
from pypdf import PdfReader
import os

&lt;span class="c"&gt;# --- CONFIGURATION ---&lt;/span&gt;
DOC_PATH &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"file.pdf"&lt;/span&gt;  &lt;span class="c"&gt;# Ensure this file exists&lt;/span&gt;
DB_PATH &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./lancedb_data"&lt;/span&gt;
MODEL_EMBED &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nomic-embed-text"&lt;/span&gt;
MODEL_GEN &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"llama3"&lt;/span&gt;

print&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"--- 🧠 Building Knowledge Base with LanceDB ---"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# 1. INGESTION: Read PDF&lt;/span&gt;
try:
    reader &lt;span class="o"&gt;=&lt;/span&gt; PdfReader&lt;span class="o"&gt;(&lt;/span&gt;DOC_PATH&lt;span class="o"&gt;)&lt;/span&gt;
    text &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;page &lt;span class="k"&gt;in &lt;/span&gt;reader.pages:
        text +&lt;span class="o"&gt;=&lt;/span&gt; page.extract_text&lt;span class="o"&gt;()&lt;/span&gt; or &lt;span class="s2"&gt;""&lt;/span&gt;
except FileNotFoundError:
    print&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="s2"&gt;"❌ Error: Could not find {DOC_PATH}. Please add a PDF file."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;# 2. CHUNKING&lt;/span&gt;
chunk_size &lt;span class="o"&gt;=&lt;/span&gt; 1000
text_chunks &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;text[i:i+chunk_size] &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;range&lt;span class="o"&gt;(&lt;/span&gt;0, len&lt;span class="o"&gt;(&lt;/span&gt;text&lt;span class="o"&gt;)&lt;/span&gt;, chunk_size&lt;span class="o"&gt;)]&lt;/span&gt;
print&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="s2"&gt;"📄 Processed {len(text_chunks)} text chunks."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# 3. EMBEDDING &amp;amp; STORAGE&lt;/span&gt;
&lt;span class="c"&gt;# LanceDB expects a list of dictionaries (like JSON rows)&lt;/span&gt;
data &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
print&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"⏳ Generating embeddings (this may take a moment)..."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;i, chunk &lt;span class="k"&gt;in &lt;/span&gt;enumerate&lt;span class="o"&gt;(&lt;/span&gt;text_chunks&lt;span class="o"&gt;)&lt;/span&gt;:
    &lt;span class="c"&gt;# Generate vector using Ollama&lt;/span&gt;
    response &lt;span class="o"&gt;=&lt;/span&gt; ollama.embeddings&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MODEL_EMBED, &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;chunk&lt;span class="o"&gt;)&lt;/span&gt;
    vector &lt;span class="o"&gt;=&lt;/span&gt; response[&lt;span class="s2"&gt;"embedding"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

    &lt;span class="c"&gt;# Prepare row for database&lt;/span&gt;
    data.append&lt;span class="o"&gt;({&lt;/span&gt;
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: i,
        &lt;span class="s2"&gt;"text"&lt;/span&gt;: chunk,
        &lt;span class="s2"&gt;"vector"&lt;/span&gt;: vector
    &lt;span class="o"&gt;})&lt;/span&gt;

&lt;span class="c"&gt;# Connect to LanceDB (creates the folder automatically)&lt;/span&gt;
db &lt;span class="o"&gt;=&lt;/span&gt; lancedb.connect&lt;span class="o"&gt;(&lt;/span&gt;DB_PATH&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Create (or overwrite) the table&lt;/span&gt;
&lt;span class="c"&gt;# vector_len depends on the model (nomic-embed-text is usually 768)&lt;/span&gt;
try:
    table &lt;span class="o"&gt;=&lt;/span&gt; db.create_table&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"resume"&lt;/span&gt;, &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;data, &lt;span class="nv"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"overwrite"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    print&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"💾 Knowledge stored in LanceDB (Local Disk)."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
except Exception as e:
    print&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="s2"&gt;"⚠️ Database error: {e}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;# 4. RETRIEVAL LOOP&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;True:
    query &lt;span class="o"&gt;=&lt;/span&gt; input&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;❓ Ask about the file (or 'quit'): "&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;query.lower&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'quit'&lt;/span&gt;: &lt;span class="nb"&gt;break&lt;/span&gt;

    &lt;span class="c"&gt;# Embed the question&lt;/span&gt;
    query_vec &lt;span class="o"&gt;=&lt;/span&gt; ollama.embeddings&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MODEL_EMBED, &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;query&lt;span class="o"&gt;)[&lt;/span&gt;&lt;span class="s2"&gt;"embedding"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

    &lt;span class="c"&gt;# Search LanceDB (Find nearest neighbors)&lt;/span&gt;
    &lt;span class="c"&gt;# .limit(1) = Get the top 1 most relevant chunk&lt;/span&gt;
    results &lt;span class="o"&gt;=&lt;/span&gt; table.search&lt;span class="o"&gt;(&lt;/span&gt;query_vec&lt;span class="o"&gt;)&lt;/span&gt;.limit&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;.to_list&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;results:
        best_chunk &lt;span class="o"&gt;=&lt;/span&gt; results[0][&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        print&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;🔍 Context Found:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;'...{best_chunk[:100]}...'"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;# 5. GENERATION&lt;/span&gt;
        prompt &lt;span class="o"&gt;=&lt;/span&gt; f&lt;span class="s2"&gt;"""
        Use the context below to answer the question.

        Context: {best_chunk}
        Question: {query}
        """&lt;/span&gt;

        response &lt;span class="o"&gt;=&lt;/span&gt; ollama.generate&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MODEL_GEN, &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prompt&lt;span class="o"&gt;)&lt;/span&gt;
        print&lt;span class="o"&gt;(&lt;/span&gt;f&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;🤖 Answer: {response['response']}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;:
        print&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"❌ No relevant info found."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the Code Works: A Quick Breakdown
&lt;/h2&gt;

&lt;p&gt;This script implements a classic Retrieval-Augmented Generation (RAG) workflow. It looks complex, but it’s just five logical steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ingestion &amp;amp; Chunking&lt;br&gt;
First, the script loads your PDF and splits its text into manageable 1,000-character pieces (“chunks”). A model can’t process a 100-page document all at once, so this step makes the information digestible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Embedding &amp;amp; Storage&lt;br&gt;
Next, it loops through each chunk and asks Ollama’s nomic-embed-text model to convert it into a vector (a list of numbers representing its meaning). These vectors, along with the original text, are saved into a LanceDB table right on your disk. Your knowledge base is now built.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Query Loop&lt;br&gt;
The script then enters a loop, waiting for you to ask a question.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retrieval&lt;br&gt;
When you enter a query, it’s also converted into a vector. LanceDB then performs a lightning-fast search to find the text chunk with the most similar vector. This is the “retrieval” step: finding the single most relevant piece of context from the entire document to answer your specific question.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generation&lt;br&gt;
Finally, the script bundles that relevant chunk with your original question into a new prompt. It sends this to Llama 3, which uses the provided context to generate a precise, accurate answer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This flywheel from your question to retrieval to a generated answer is what makes the magic happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Put Your Assistant to Work (Real-World Examples)
&lt;/h2&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%2Frfgm6p7a94u4ne99xes5.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.amazonaws.com%2Fuploads%2Farticles%2Frfgm6p7a94u4ne99xes5.webp" alt="Photo by Aerps.com on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the script is just the start. The real power is in the quality of your questions.&lt;/p&gt;

&lt;p&gt;I tested this with a dense, jargon-filled financial document: “Meta Reports Third Quarter 2025 Results.”&lt;/p&gt;

&lt;p&gt;Here’s how a simple script transforms into a powerful analytical partner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Instantly Summarize Complex Financial Reports
&lt;/h3&gt;

&lt;p&gt;The document is full of SEC boilerplate and investor-speak. My goal was to cut through the noise and get the most critical information, fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Summarize the key financial highlights from this report in three bullet points. Focus on revenue, net income, and daily active users.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;AI’s Response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤖 Answer: Here are the key financial highlights summarized in three bullet points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Revenue: Revenue was $51.24 billion, an increase of 26% year-over-year (25% on a constant currency basis).&lt;/li&gt;
&lt;li&gt;Net Income: No net income figure is mentioned in this report, only revenue and other financial metrics.&lt;/li&gt;
&lt;li&gt;Daily Active Users (DAU): Family daily active people (DAP) was 3.54 billion on average for September 2025, an increase of 8% year-over-year.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In seconds, you get the core metrics without reading 20 pages. This is perfect for grasping the essentials before a meeting or making a quick decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2: Prepare for a High-Stakes Stakeholder Meeting
&lt;/h3&gt;

&lt;p&gt;Now, let’s move beyond simple data extraction.&lt;/p&gt;

&lt;p&gt;Imagine you have to present these findings to skeptical stakeholders. You can use the AI to pressure-test your arguments and anticipate difficult questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Assume the role of a skeptical board member. Based on this report, what are the three most challenging questions you would ask me about the company’s performance and future outlook?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;AI’s Response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤖 Answer: As a skeptical board member, I’d want to drill down into the details and potential risks associated with the company’s performance and future outlook. Here are three challenging questions I’d ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What specific factors are driving the uncertainty around dividend payments? You mentioned “market conditions or other factors” as potential risks affecting dividend payments. Can you provide more granularity on what exactly these factors are, and how they might impact our investors? Are we talking about changes in interest rates, economic downturns, or something else entirely?&lt;/li&gt;
&lt;li&gt;What is the company doing to mitigate these risks and ensure a stable financial future? Given the uncertainty around dividend payments, I’d want to know if the company has implemented any strategies to reduce its exposure to market fluctuations or other external factors. Are we investing in diversification initiatives, hedging instruments, or other risk-reduction measures?&lt;/li&gt;
&lt;li&gt;How confident are you that our quarterly reports will continue to accurately reflect the company’s performance and future outlook? You mention that forward-looking statements are based on assumptions that seem reasonable as of October 29, 2025, but I’d want more assurance that these assumptions won’t change dramatically in the coming quarters. Can we get a sense of what specific factors might lead us to revisit or revise our quarterly reports going forward?&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a game-changer. Your private AI just became your personal sparring partner, helping you walk into a critical presentation prepared and confident.&lt;/p&gt;

&lt;p&gt;This isn’t just a fun project. It’s a foundational step towards building truly sovereign AI applications. The tools are free, the data is yours, and the power is back on your machine.&lt;/p&gt;

&lt;p&gt;Now go build something.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Run LangChain Locally in 15 Minutes (Without a Single API Key)</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 04 Nov 2025 21:55:47 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/run-langchain-locally-in-15-minutes-without-a-single-api-key-1j8m</link>
      <guid>https://dev.to/fabiothiroki/run-langchain-locally-in-15-minutes-without-a-single-api-key-1j8m</guid>
      <description>&lt;p&gt;You don’t need an API key.&lt;/p&gt;

&lt;p&gt;That’s the secret everyone seems to forget.&lt;/p&gt;

&lt;p&gt;I wanted to dive into LangChain, the powerful framework for building with Large Language Models. But every guide, even the official docs, felt like a trap. They were outdated, incomplete, or pushed me toward a paid Anthropic key.&lt;/p&gt;

&lt;p&gt;I wrestled with Python version errors. I hunted for missing dependencies. It was a frustrating maze designed to make me quit.&lt;/p&gt;

&lt;p&gt;So I carved my own path.&lt;/p&gt;

&lt;p&gt;This is the guide I wish I had. It’s your shortcut to running a powerful LLM on your own machine, completely for free, in the next 15 minutes.&lt;/p&gt;

&lt;p&gt;P.S.: If you want to skip the article, you can check the code directly on &lt;a href="https://github.com/fabiothiroki/langchain-quickstart" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. First, understand why this is a game-changer.
&lt;/h2&gt;

&lt;p&gt;Running an LLM locally is about one thing: speed.&lt;/p&gt;

&lt;p&gt;Not processing speed, but the speed of learning.&lt;/p&gt;

&lt;p&gt;When you're just trying to get a feel for a new framework, the last thing you want is a roadblock. You don't need to sign up for an API, enter a credit card, or wait for an approval email just to run a "hello, world" prompt.&lt;/p&gt;

&lt;p&gt;This local-first approach removes all that friction.&lt;/p&gt;

&lt;p&gt;And as a bonus, it comes with three other superpowers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero Cost: It’s completely free, no matter how many prompts you run.&lt;/li&gt;
&lt;li&gt;Total Privacy: Your data never leaves your machine.&lt;/li&gt;
&lt;li&gt;Full Control: You choose the model, you own the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just about saving money. It's about creating the fastest path to actually building and learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Next, get your environment right (this is critical).
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Up Your Python Version.
&lt;/h3&gt;

&lt;p&gt;This is where 99% of tutorials fail. They give vague instructions, but the AI world moves so fast that packages break between minor versions. We will avoid that entirely.&lt;/p&gt;

&lt;p&gt;This tutorial was built and verified using Python 3.13.0. Sticking to this exact version removes any guesswork. For managing Python versions like a pro, I recommend &lt;a href="https://github.com/pyenv/pyenv" rel="noopener noreferrer"&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pyenv &lt;span class="nb"&gt;install &lt;/span&gt;3.13.0
pyenv &lt;span class="nb"&gt;local &lt;/span&gt;3.13.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Ollama.
&lt;/h3&gt;

&lt;p&gt;Ollama is the magic that runs the LLM on your machine. Go to &lt;a href="https://ollama.com/download/" rel="noopener noreferrer"&gt;https://ollama.com/download/&lt;/a&gt; and download it for your system. Install it like any other application. It will run quietly in the background, ready when you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Now, start Ollama and download your AI model.
&lt;/h2&gt;

&lt;p&gt;With Ollama installed, you need to make sure its server is running before you can download or use a model.&lt;/p&gt;

&lt;p&gt;Open a new, separate terminal window and run this command. Leave this terminal running in the background.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: If you get an error that the server is already running, that's fine—it means the app started automatically.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, in your original terminal, pull the llama3.2 model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull llama3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might take a few minutes. You only have to pull once.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Then, install the exact package versions.
&lt;/h2&gt;

&lt;p&gt;To guarantee this works, we will install the exact library versions used in this tutorial.&lt;/p&gt;

&lt;p&gt;First, create a project folder and set up a virtual environment (a critical best practice):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, install the pinned dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;langchain&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.0.3 langchain-ollama&lt;span class="o"&gt;==&lt;/span&gt;1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures you have the precise code that we know works. No surprises, no cryptic error messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Finally, write less than 20 lines of Python code.
&lt;/h2&gt;

&lt;p&gt;You have the environment, the model, and the libraries. All that's left is to connect them.&lt;/p&gt;

&lt;p&gt;Create a new Python file named main.py and paste in the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_ollama&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOllama&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get weather for a given city.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return the weather in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in a joke.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ChatOllama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Run the agent
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;what is the weather in sf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code creates the model, defines a simple instruction, chains them together, and asks a question. That’s the core of LangChain in action.&lt;/p&gt;

&lt;p&gt;In your terminal, run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fog-get about it, it's always raining in San Francisco!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;You just ran a state-of-the-art LLM on your local machine using LangChain. You've bypassed the confusing docs, avoided all API keys, and built something that is 100% free and private.&lt;/p&gt;

&lt;p&gt;Now, what will you build next?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
      <category>langchain</category>
    </item>
    <item>
      <title>Como eu uso IA de graça para transformar podcasts em lições práticas</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Thu, 18 Sep 2025 15:43:45 +0000</pubDate>
      <link>https://dev.to/portugues/como-eu-uso-ia-de-graca-para-transformar-podcasts-em-licoes-praticas-32k7</link>
      <guid>https://dev.to/portugues/como-eu-uso-ia-de-graca-para-transformar-podcasts-em-licoes-praticas-32k7</guid>
      <description>&lt;p&gt;Vamos ser honestos: &lt;strong&gt;o quanto do último podcast que você ouviu você realmente lembra?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se você é como a maioria das pessoas, a resposta provavelmente é "não muito". Passamos horas toda semana consumindo conselhos incríveis e transformadores das pessoas mais inteligentes do mundo, apenas para que tudo desapareça de nossas mentes em 48 horas. A lacuna entre ouvir e fazer é gigantesca.&lt;/p&gt;

&lt;p&gt;Aqui está o truque de IA gratuito que eu uso para consertar isso.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Truque: De Podcast a Plano de Ação em 60 Segundos
&lt;/h2&gt;

&lt;p&gt;Aqui está o único passo que você precisa:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pegue a URL do YouTube&lt;/strong&gt; do podcast que você quer analisar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abra o &lt;a href="https://notebooklm.google.com/" rel="noopener noreferrer"&gt;NotebookLM do Google&lt;/a&gt;&lt;/strong&gt; e clique em “Create New“ (Criar Novo).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clique em “Youtube” e cole a URL&lt;/strong&gt; como uma nova fonte.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use este prompt&lt;/strong&gt; no chat:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Você é um analista de tecnologia especialista em traduzir conceitos amplos em conselhos acionáveis para engenheiros de software. Meu objetivo é extrair as ideias mais relevantes e aplicáveis desta fonte para o meu trabalho.

Instruções:
Analise a fonte fornecida da perspectiva de um engenheiro de software. Identifique os 3 principais conceitos, modelos mentais ou estratégias que são mais aplicáveis ao campo da engenharia de software.

Para cada conceito que você identificar, apresente-o usando a seguinte estrutura clara e concisa. Não me faça perguntas; forneça a informação diretamente.

🚀 Conceito 1: [Nome do Conceito]

Explicação Simples: Em 1-2 frases, o que é este conceito em termos simples, de acordo com o podcast? Forneça uma citação direta do palestrante que melhor encapsula a ideia.

Relevância para Engenheiros: Por que este conceito é particularmente relevante para o desenvolvimento de software, dinâmica de equipe, resolução de problemas ou arquitetura de sistemas?

Aplicação Prática: Forneça um exemplo concreto de como posso aplicar este conceito no meu trabalho esta semana. (ex: uma pergunta a ser feita em uma revisão de código, um princípio para projetar uma nova funcionalidade, uma maneira de me comunicar com minha equipe).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A verdadeira mágica aqui está na primeira linha: "Você é um especialista..." Isso é chamado de "prompt com persona", e é a chave para obter resultados hiper-relevantes.&lt;/p&gt;

&lt;p&gt;Você pode, e deve, alterar isso para se adequar à sua própria vida e trabalho. Dica Pro: Você pode usar uma LLM para editar o prompt para você.&lt;/p&gt;

&lt;h2&gt;
  
  
  Colocando à Prova: Um Exemplo do Mundo Real
&lt;/h2&gt;

&lt;p&gt;Eu executei exatamente esse fluxo de trabalho em um podcast recente de Lenny Rachitsky sobre o Mercado Livre:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/puY_dxVKEwU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Aqui está o resultado do NotebookLM:&lt;/p&gt;

&lt;p&gt;Como um analista de tecnologia especialista, analisei a fonte fornecida para identificar os conceitos mais relevantes e aplicáveis para engenheiros de software. Aqui estão os três principais, apresentados com conselhos práticos para o seu trabalho:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Conceito 1: Propriedade Integrada de Produto e Engenharia&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicação Simples&lt;/strong&gt;: No Mercado Livre, há uma indefinição deliberada das linhas entre as funções de engenharia e produto, com uma forte ênfase nos engenheiros assumindo uma propriedade significativa das decisões de produto. O objetivo não é determinar a propriedade pelo cargo, mas por quem é mais adequado para a função, muitas vezes os próprios líderes de engenharia. Como afirma Sebastian Barrios, “é difícil separar onde a engenharia para e o produto começa, e não sentimos que apenas ter um título deveria determinar quem é o dono”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relevância para Engenheiros:&lt;/strong&gt; Este conceito é profundamente relevante para o desenvolvimento de software porque impulsiona os engenheiros para além da mera implementação técnica, para uma compreensão holística do produto, dos usuários e das necessidades do negócio. Ele fomenta um senso mais profundo de responsabilidade pelo sucesso do produto, garantindo que a viabilidade técnica se alinhe perfeitamente com o valor para o usuário e os objetivos de negócio. Espera-se que os engenheiros combinem a compreensão do “que é tecnicamente possível” com “quais são as necessidades do negócio, quais são as necessidades dos usuários, o que os usuários estão fazendo, como vou medir isso”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aplicação Prática:&lt;/strong&gt; Ao projetar ou implementar uma nova funcionalidade esta semana, &lt;strong&gt;envolva-se ativamente com seu contexto de negócio e de usuário&lt;/strong&gt;. Antes de escrever o código, pergunte a si mesmo: “Como o usuário experimentará esse fluxo, e ele o está entendendo?”. Considere o impacto pretendido da funcionalidade no usuário e como seu sucesso seria medido, em vez de focar apenas nos requisitos técnicos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🚀 Conceito 2: Viés por Expertise Técnica Profunda&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicação Simples:&lt;/strong&gt; O Mercado Livre valoriza muito os engenheiros que possuem conhecimento técnico profundo e estão intimamente familiarizados com os detalhes da tecnologia que usam. Há um “forte viés para a engenharia, para ser técnico, para estar a fundo nos detalhes”. Isso significa uma baixa tolerância para compreensão superficial ou para depender de outros para especificidades técnicas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relevância para Engenheiros:&lt;/strong&gt; Para engenheiros de software, este modelo mental enfatiza a importância crítica do domínio técnico. Ele promove a construção de sistemas robustos e escaláveis e permite que os engenheiros liderem discussões de forma eficaz, sem precisar consultar outros para obter informações técnicas fundamentais. Essa compreensão técnica profunda é crucial para a resolução eficiente de problemas, decisões de arquitetura e manutenção de uma alta qualidade nas implantações.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aplicação Prática:&lt;/strong&gt; Em sua próxima discussão técnica ou revisão de código, esteja preparado para articular os detalhes técnicos subjacentes da sua solução ou de um componente que você está revisando. Em vez de dizer “preciso verificar com fulano para entender os detalhes,” esforce-se para fornecer você mesmo uma explicação abrangente da tecnologia, suas escolhas e suas implicações.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀 &lt;strong&gt;Conceito 3: Incentivo à Tomada de Risco e Aprendizado com Falhas de 'Mercado'&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicação Simples:&lt;/strong&gt; A empresa fomenta uma cultura onde as equipes são encorajadas a correr riscos e não são penalizadas por lançar funcionalidades que possam falhar devido à recepção do mercado ou a ideias falhas. Sebastian Barrios afirma, “nós realmente empoderamos nossas equipes para cometer erros, tipo, ninguém vai ser demitido por lançar algo que não funcionou no sentido de que talvez o mercado não estivesse pronto ou tivéssemos a ideia errada sobre onde implementar”. Isso contrasta com uma baixa tolerância a falhas relacionadas à má qualidade ou a interrupções do sistema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relevância para Engenheiros:&lt;/strong&gt; Essa estratégia é vital para a inovação no desenvolvimento de software. Ela permite que os engenheiros experimentem novas ideias e funcionalidades, fomentando a criatividade e um ciclo de aprendizado rápido, sem o medo paralisante de repercussões negativas por resultados fora da qualidade técnica. Ela apoia diretamente uma “alta velocidade de execução” em um mercado dinâmico, priorizando o aprendizado e a adaptação.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aplicação Prática:&lt;/strong&gt; Esta semana, ao propor uma nova funcionalidade ou uma mudança significativa, enquadre-a como um experimento com hipóteses claras sobre a recepção do usuário ou do mercado. Seja explícito sobre as suposições que estão sendo testadas e como o sucesso ou o fracasso (em termos de adequação ao mercado, não de qualidade técnica) fornecerá um aprendizado valioso para iterações futuras. Essa abordagem encoraja visões ousadas e pivôs rápidos se as suposições iniciais se mostrarem incorretas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Apenas a Ponta do Iceberg
&lt;/h2&gt;

&lt;p&gt;E esse é o cerne do truque. É um sistema simples e repetível para transformar o consumo passivo em crescimento ativo.&lt;/p&gt;

&lt;p&gt;O NotebookLM é uma ferramenta poderosa que pode fazer muito mais, mas eu queria manter este artigo curto e focado no único fluxo de trabalho que mais me deu resultados.&lt;/p&gt;

&lt;p&gt;Se você achou isso útil e está interessado em mais conteúdo como este, por favor, me avise! A melhor maneira de fazer isso é deixar um comentário ou clicar no botão 👏 abaixo.&lt;/p&gt;

&lt;p&gt;Ficarei feliz em compartilhar mais dicas e truques sobre como uso IA para aprendizado e produtividade. Me diga o que você gostaria de ver a seguir.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>learning</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>My free AI trick to turn podcasts into actionable life lessons</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 09 Sep 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/my-free-ai-trick-to-turn-podcasts-into-actionable-life-lessons-3m3e</link>
      <guid>https://dev.to/fabiothiroki/my-free-ai-trick-to-turn-podcasts-into-actionable-life-lessons-3m3e</guid>
      <description>&lt;p&gt;Let's be honest: &lt;strong&gt;how much of the last podcast you listened to do you actually remember?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re like most people, the answer is probably "not much." We spend hours every week consuming incredible, life-changing advice from the world's smartest people, only for it to vanish from our minds within 48 hours. The gap between listening and doing is massive.&lt;/p&gt;

&lt;p&gt;Here’s the free AI trick I use to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trick: From Podcast to Action Plan in 60 Seconds
&lt;/h2&gt;

&lt;p&gt;Here’s the only step you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grab the YouTube URL&lt;/strong&gt; of the podcast you want to analyze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open &lt;a href="https://notebooklm.google.com/" rel="noopener noreferrer"&gt;Google's NotebookLM&lt;/a&gt;&lt;/strong&gt; and click “Create New“.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Click “Youtube” and paste the URL&lt;/strong&gt; as a new source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use this prompt&lt;/strong&gt; in the chat:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert tech analyst specializing in translating broad concepts into actionable advice for software engineers. My goal is to extract the most relevant and applicable ideas from this source for my work.

Instructions:
Analyze the provided source from the perspective of a software engineer. Identify the top 3 concepts, mental models, or strategies that are most applicable to the field of software engineering.

For each concept you identify, present it using the following clear and concise structure. Do not ask me questions; provide the information directly.

### 🚀 Concept 1: [Name of the Concept]
* **Simple Explanation:** In 1-2 sentences, what is this concept in simple terms, according to the podcast? provide a direct quote from the speaker that best encapsulates the idea.
* **Relevance for Engineers:** Why is this concept particularly relevant to software development, team dynamics, problem-solving, or system architecture?
* **Actionable Application:** Provide one concrete example of how I can apply this concept in my work this week. (e.g., a question to ask in a code review, a principle for designing a new feature, a way to communicate with my team).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real magic here is the first line: "You are an expert..." This is called "prompting with a persona," and it's the key to getting hyper-relevant results.&lt;/p&gt;

&lt;p&gt;You can, and should, change this to suit your own life and work. Pro-Tip: You can use an LLM to edit the prompt for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It to the Test: A Real-World Example
&lt;/h2&gt;

&lt;p&gt;I ran this exact workflow on a recent podcast from Lenny Rachitsky&lt;br&gt;
about Mercado Libre:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/puY_dxVKEwU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here’s the output from NotebookLM:&lt;/p&gt;

&lt;p&gt;As an expert tech analyst, I’ve analyzed the provided source to identify the most relevant and applicable concepts for software engineers. Here are the top three, presented with actionable advice for your work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Concept 1: Integrated Product-Engineering Ownership&lt;/strong&gt;&lt;br&gt;
• &lt;strong&gt;Simple Explanation&lt;/strong&gt;: At Mercado Libre, there’s a deliberate blurring of lines between engineering and product roles, with a strong emphasis on engineers taking significant ownership of product decisions. The aim is not to determine ownership by title, but by who is best suited for the role, often the engineering leaders themselves. As Sebastian Barrios states, “it’s hard to separate where engineering stops and product begins and we don’t feel like just having a title should determine who is the owner”&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Relevance for Engineers:&lt;/strong&gt; This concept is profoundly relevant to software development because it pushes engineers beyond mere technical implementation into a holistic understanding of the product, users, and business needs. It fosters a deeper sense of responsibility and accountability for the product’s success, ensuring that technical feasibility aligns seamlessly with user value and business objectives. Engineers are expected to combine understanding of “what’s technically possible” with “what are the business needs what are the user needs what are the users doing how am I going to measure that”.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Actionable Application:&lt;/strong&gt; When designing or implementing a new feature this week, &lt;strong&gt;actively engage with its business and user context&lt;/strong&gt;. Before writing code, ask yourself: “How will the user experience this flow, and are they understanding it?”. Consider the feature’s intended user impact and how its success would be measured, rather than just focusing on the technical requirements alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Concept 2: Bias for Deep Technical Expertise&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Simple Explanation:&lt;/strong&gt; Mercado Libre places a high value on engineers who possess deep technical knowledge and are intimately familiar with the details of the technology they use. There is a “strong bias for engineering for for for being technical for being deep into the details”. This means a low tolerance for superficial understanding or deferring to others for technical specifics.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Relevance for Engineers:&lt;/strong&gt; For software engineers, this mental model emphasizes the critical importance of technical mastery. It promotes building robust, scalable systems and allows engineers to lead discussions effectively without needing to consult others for fundamental technical information. This deep technical understanding is crucial for efficient problem-solving, architectural decisions, and maintaining a high quality of deployments.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Actionable Application:&lt;/strong&gt; In your next technical discussion or code review, be prepared to articulate the underlying technical details of your solution or a component you’re reviewing. Instead of saying “I need to check with this person to understand the details,” strive to provide a comprehensive explanation of the technology, its choices, and its implications yourself.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Concept 3: Empowering Risk-Taking and Learning from ‘Market’ Failures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Simple Explanation:&lt;/strong&gt; The company fosters a culture where teams are encouraged to take risks and are not penalized for releasing features that might fail due to market reception or flawed ideas. Sebastian Barrios states, “we actually empower our teams to to to make mistakes like no one’s going to get fired for releasing something that didn’t work in the sense that maybe the market was not ready or we had the wrong idea on on on where had to implement”. This contrasts with a low tolerance for failures related to bad quality or system outages.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Relevance for Engineers:&lt;/strong&gt; This strategy is vital for innovation in software development. It enables engineers to experiment with new ideas and features, fostering creativity and a rapid learning cycle without the paralyzing fear of negative repercussions for outcomes outside of technical quality. It directly supports a “high speed of execution” in a dynamic market by prioritizing learning and adaptation.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Actionable Application:&lt;/strong&gt; This week, when proposing a new feature or a significant change, frame it as an experiment with clear hypotheses about user or market reception. Be explicit about the assumptions being tested and how success or failure (in terms of market fit, not technical quality) will provide valuable learning for future iterations. This approach encourages bold visions and swift pivots if initial assumptions prove incorrect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just the Tip of the Iceberg
&lt;/h2&gt;

&lt;p&gt;And that’s the core of the trick. It’s a simple, repeatable system for turning passive consumption into active growth.&lt;/p&gt;

&lt;p&gt;NotebookLM is a powerful tool that can do much more, but I wanted to keep this article short and focused on the one workflow that has given me the most leverage.&lt;/p&gt;

&lt;p&gt;If you found this useful and are interested in more content like this, please let me know! The best way to do that is to leave a comment or hit the 👏 button below.&lt;/p&gt;

&lt;p&gt;I’ll be happy to share more tips and tricks on how I use AI for learning and productivity. Let me know what you’d like to see next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>learning</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Fri, 22 Aug 2025 06:42:08 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/-52il</link>
      <guid>https://dev.to/fabiothiroki/-52il</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/pradumnasaraf/running-ai-models-with-docker-compose-27ng" class="crayons-story__hidden-navigation-link"&gt;Running AI Models with Docker Compose&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/pradumnasaraf" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F682769%2F6d44570c-3d95-4656-ba55-c8a4b0e95f9e.jpg" alt="pradumnasaraf profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/pradumnasaraf" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Pradumna Saraf
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Pradumna Saraf
                
              
              &lt;div id="story-author-preview-content-2771959" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/pradumnasaraf" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F682769%2F6d44570c-3d95-4656-ba55-c8a4b0e95f9e.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Pradumna Saraf&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/pradumnasaraf/running-ai-models-with-docker-compose-27ng" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 19 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/pradumnasaraf/running-ai-models-with-docker-compose-27ng" id="article-link-2771959"&gt;
          Running AI Models with Docker Compose
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/pradumnasaraf/running-ai-models-with-docker-compose-27ng" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;49&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/pradumnasaraf/running-ai-models-with-docker-compose-27ng#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              23&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>docker</category>
      <category>ai</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Perseguindo uma Vida Melhor: Como Consegui um Emprego em Tecnologia no Exterior</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 17 Jun 2025 15:43:54 +0000</pubDate>
      <link>https://dev.to/portugues/perseguindo-uma-vida-melhor-como-consegui-um-emprego-em-tecnologia-no-exterior-2h7k</link>
      <guid>https://dev.to/portugues/perseguindo-uma-vida-melhor-como-consegui-um-emprego-em-tecnologia-no-exterior-2h7k</guid>
      <description>&lt;p&gt;Você já sonhou em se mudar para outro país — começar do zero em um lugar novo, com novas oportunidades e uma melhor qualidade de vida? Para muitos engenheiros de software, a ideia de trabalhar no exterior é ao mesmo tempo empolgante e intimidadora. Eu sei, porque já passei por isso.&lt;/p&gt;

&lt;p&gt;Nasci e cresci no Brasil, um país em desenvolvimento onde, mesmo como engenheiro de software, a vida traz seus próprios desafios. Embora a profissão possa oferecer um salário confortável, o dia a dia era frequentemente ofuscado por preocupações com segurança — coisas simples como usar o celular em público ou caminhar para casa à noite se tornavam fontes de ansiedade. Quando comecei a pensar em formar uma família, essas preocupações cresceram ainda mais. Eu sabia que não queria que meu filho crescesse em um lugar onde a segurança estivesse sempre na minha mente.&lt;/p&gt;

&lt;p&gt;Então veio a pandemia, que só aumentou minha frustração e sensação de inquietação. Foi então que tomei uma decisão: buscar oportunidades no exterior, em países que oferecessem não apenas um emprego, mas uma vida mais segura e equilibrada.&lt;/p&gt;

&lt;p&gt;Neste artigo, compartilharei minha jornada, desde o planejamento e a preparação até a busca por emprego — até o momento em que recebi minha primeira oferta. Se você já considerou fazer uma mudança semelhante, ou se está apenas curioso sobre o que é necessário para se mudar como engenheiro de software, espero que minha história inspire e oriente você.&lt;/p&gt;

&lt;h2&gt;
  
  
  Planejamento e Pesquisa: Mantendo Simples
&lt;/h2&gt;

&lt;p&gt;Olhando para trás, admito que minha fase de planejamento não foi tão meticulosa quanto alguns recomendariam. Não passei meses comparando todos os países ou construindo planilhas detalhadas. Em vez disso, adotei uma abordagem mais direta — alguns diriam até imprudente.&lt;/p&gt;

&lt;p&gt;Meus principais critérios eram simples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empresas em países desenvolvidos&lt;/li&gt;
&lt;li&gt;Patrocínio de visto disponível&lt;/li&gt;
&lt;li&gt;Bom equilíbrio entre trabalho e vida pessoal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com esses filtros em mente, concentrei minha busca de emprego na Europa. Pulei as análises profundas de comparações de custo de vida e caminhos complexos de imigração — pelo menos no início. Minha prioridade era encontrar empresas dispostas a patrocinar meu visto, já que esse era o maior obstáculo para a mudança.&lt;/p&gt;

&lt;p&gt;Claro, à medida que comecei a receber respostas de empregadores e aprendi mais sobre o processo, comecei a pesquisar os detalhes — como salários locais, sistema de saúde e como seria a vida em cada cidade. Mas, no começo, deixei meu desejo por uma vida mais segura e equilibrada me guiar, mantendo o planejamento intencionalmente simples para evitar me sentir sobrecarregado.&lt;/p&gt;

&lt;p&gt;Olhando para trás, percebo que, embora um plano mais detalhado pudesse ter ajudado, às vezes tomar ação é o passo mais importante. Para quem está pensando em fazer uma mudança semelhante, não deixe o perfeccionismo te impedir de começar. Você sempre pode refinar seu plano ao longo do caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparação e Busca de Emprego: Preparando-se e Agindo
&lt;/h2&gt;

&lt;p&gt;Com a Europa como meu alvo e o patrocínio de visto como uma exigência, meu próximo passo foi preparar meus materiais de candidatura e começar a buscar oportunidades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atualizando Meu Currículo e Presença Online
&lt;/h3&gt;

&lt;p&gt;Eu sabia que um currículo forte e um perfil no LinkedIn eram cruciais para chamar a atenção dos recrutadores. Atualizei ambos para incluir métricas específicas que demonstravam o impacto do meu trabalho. Em vez de apenas listar responsabilidades, adicionei números e resultados — como melhorias no desempenho de aplicativos, redução de tempo de inatividade ou aumento no engajamento de usuários. Isso ajudou a mostrar aos recrutadores não apenas o que fiz, mas como meu trabalho fez a diferença.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focando em Empresas que Patrocinam Vistos
&lt;/h3&gt;

&lt;p&gt;Concentrei minha busca de emprego em empresas na Europa que ofereciam patrocínio de visto. Usei quadros de empregos e filtros para identificar essas oportunidades e prestei atenção às avaliações de empresas e ao equilíbrio entre trabalho e vida pessoal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Começando Antes de Me Sentir Totalmente Preparado
&lt;/h3&gt;

&lt;p&gt;Embora eu não me sentisse 100% preparado para as entrevistas, decidi começar a me candidatar mesmo assim. Sabia que esperar o “momento perfeito” poderia significar perder oportunidades reais. Todas as minhas entrevistas foram em inglês, que não é minha língua materna, então essas primeiras entrevistas se tornaram sessões de prática extremamente valiosas. Elas me ajudaram a ficar confortável falando sobre minha experiência e habilidades em um ambiente profissional — algo que eu não fazia muito antes. Essa experiência aumentou minha confiança e habilidades de comunicação, mesmo enquanto continuava a estudar e melhorar. Reconheço que essa abordagem não funciona para todas as empresas, especialmente aquelas com processos de recrutamento longos ou altamente competitivos. Mas, para mim, agir cedo foi uma forma de aprender fazendo, em vez de esperar até me sentir completamente pronto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lidando com Candidaturas e Entrevistas: Aprendendo na Prática
&lt;/h2&gt;

&lt;p&gt;Uma vez que comecei a me candidatar, o processo real começou. Cada candidatura exigia atenção cuidadosa, mas as entrevistas foram onde as coisas ficaram interessantes — e, às vezes, desafiadoras.&lt;/p&gt;

&lt;h3&gt;
  
  
  O Processo de Candidatura
&lt;/h3&gt;

&lt;p&gt;Sempre que havia a opção de enviar uma carta de apresentação, eu aproveitava para personalizá-la de acordo com os produtos, missão e objetivos da empresa. Aprendi que uma carta de apresentação bem elaborada e personalizada pode fazer uma grande diferença — ela ajuda você a se destacar entre outros candidatos e mostra aos recrutadores que você fez sua lição de casa e está genuinamente interessado em contribuir para o sucesso da empresa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiências em Entrevistas
&lt;/h3&gt;

&lt;p&gt;Todas as minhas entrevistas foram em inglês, o que adicionou uma camada extra de complexidade. Meu inglês estava longe de ser “perfeito”, e às vezes eu não entendia completamente o que o entrevistador dizia. Mesmo assim, consegui me comunicar bem o suficiente para transmitir minhas ideias. Na maioria das vezes, os entrevistadores foram pacientes e compreensivos.&lt;/p&gt;

&lt;p&gt;Essa experiência me ensinou que você não precisa esperar até que seu inglês esteja perfeito para começar a fazer entrevistas. O que importa é ser capaz de se expressar com clareza e confiança, mesmo que cometa erros ao longo do caminho.&lt;/p&gt;

&lt;p&gt;Enquanto me candidatava, também estudava todos os dias — praticar algoritmos, estruturas de dados, design de sistemas e perguntas comportamentais se tornou parte da minha rotina. Durante as entrevistas, prestei muita atenção à linguagem corporal e às reações dos entrevistadores. Se uma resposta minha não gerava uma reação positiva ou parecia errada, eu considerava isso um feedback indireto. Isso me ajudou a identificar áreas onde precisava melhorar e a focar meus estudos para entrevistas futuras.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aprendendo com Rejeições
&lt;/h3&gt;

&lt;p&gt;Nem toda entrevista resultou em uma oferta. Houve rejeições, e às vezes o feedback era difícil de ouvir. Mas tentei ver cada uma como uma oportunidade de aprendizado. Prestei atenção às perguntas com as quais tive dificuldade e as usei para guiar minhas sessões de estudo. Com o tempo, fiquei melhor em antecipar o que os entrevistadores queriam e como me apresentar como um candidato forte.&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%2Fadint2smq3f8jq8vznfj.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.amazonaws.com%2Fuploads%2Farticles%2Fadint2smq3f8jq8vznfj.webp" alt="Photo by Pablo Heimplatz on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recebendo uma Oferta e Reflexões
&lt;/h2&gt;

&lt;p&gt;Após semanas de candidaturas, entrevistas e muito estudo, finalmente recebi uma oferta de uma empresa na Europa. Esse momento marcou um marco importante na minha jornada — não apenas porque significava que eu poderia me mudar, mas porque validou todo o esforço e persistência que investi.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Oferta e o Que Ela Significou
&lt;/h3&gt;

&lt;p&gt;Quando a oferta chegou, senti uma mistura de empolgação e alívio. Depois de tanta incerteza — especialmente como alguém que nunca havia vivido ou trabalhado no exterior antes —, foi reconfortante saber que minhas habilidades e experiência foram reconhecidas. A empresa estava disposta a patrocinar meu visto, o que significava que eu poderia finalmente começar a planejar minha mudança e um novo capítulo para minha família.&lt;/p&gt;

&lt;h3&gt;
  
  
  Olhando para Trás no Processo
&lt;/h3&gt;

&lt;p&gt;Olhando para trás, percebi o quanto aprendi — não apenas sobre tópicos técnicos, mas sobre mim mesmo e do que sou capaz. Superei barreiras linguísticas, me adaptei a diferentes estilos de entrevista e lidei com rejeições com resiliência. Cada passo, mesmo os mais difíceis, me tornou mais forte e mais preparado para os desafios à frente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Principais Lições
&lt;/h3&gt;

&lt;p&gt;Aqui estão as lições mais importantes que aprendi ao longo do caminho:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comece Antes de Estar Pronto: Não espere o “momento perfeito”. Comece a se candidatar e fazer entrevistas o quanto antes — você aprenderá e melhorará com cada experiência.&lt;/li&gt;
&lt;li&gt;Personalize Sua Candidatura: Sempre envie uma carta de apresentação personalizada quando possível. Mostre aos recrutadores que você entende a empresa e como pode contribuir.&lt;/li&gt;
&lt;li&gt;Use Entrevistas como Prática: Mesmo que esteja nervoso ou seu inglês não seja perfeito, use cada entrevista como uma chance de aprender e crescer.&lt;/li&gt;
&lt;li&gt;Preste Atenção ao Feedback: Observe as reações dos entrevistadores e use-as como feedback indireto para guiar seus estudos e preparação.&lt;/li&gt;
&lt;li&gt;Permaneça Persistente: Rejeições fazem parte do processo. Aprenda com elas, ajuste sua abordagem e continue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este artigo é uma visão geral da minha experiência em conseguir um emprego no exterior. Se você quiser que eu mergulhe mais fundo em alguma parte específica — como estudei, como organizei minhas candidaturas, como gerenciei meu tempo enquanto trabalhava em tempo integral, ou qualquer outro tópico —, por favor, deixe um comentário! Seu feedback me ajudará a decidir no que focar em artigos futuros.&lt;/p&gt;

&lt;p&gt;Vamos aprender e crescer juntos!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>watercooler</category>
      <category>interview</category>
    </item>
    <item>
      <title>Chasing a Better Life: How I Landed a Tech Job Abroad</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 17 Jun 2025 06:28:07 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/chasing-a-better-life-how-i-landed-a-tech-job-abroad-4fi6</link>
      <guid>https://dev.to/fabiothiroki/chasing-a-better-life-how-i-landed-a-tech-job-abroad-4fi6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Have you ever dreamed of relocating to another country-of starting fresh in a new place, with new opportunities and a better quality of life?&lt;/strong&gt; For software engineers, the prospect of working abroad is both thrilling and intimidating. I know this firsthand.&lt;/p&gt;

&lt;p&gt;As a software engineer born and raised in Brazil, I faced challenges that went beyond code. Despite a comfortable salary, daily life was overshadowed by safety concerns-simple acts like using my phone in public or walking home at night felt risky. When I started thinking about raising a family, those worries grew. Then the pandemic hit, amplifying my frustration and pushing me to seek a safer, more stable future abroad.&lt;/p&gt;

&lt;p&gt;In this article, I’ll share my journey from planning and preparation to landing my first job offer overseas. From navigating visas to acing interviews, I hope my story inspires and equips you to take your own leap as a software engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Planning and Research: Keeping It Simple
&lt;/h2&gt;

&lt;p&gt;I’ll be honest: my planning phase wasn’t a masterclass in organization. I didn’t spend months comparing countries or building intricate spreadsheets. Instead, I took a straightforward-some might call it reckless-approach to kickstart my relocation journey.&lt;/p&gt;

&lt;p&gt;My criteria were clear and simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Companies in developed countries&lt;/li&gt;
&lt;li&gt;Visa sponsorship available&lt;/li&gt;
&lt;li&gt;Good work-life balance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these filters, I zeroed in on Europe, drawn to its tech hubs like Berlin and Amsterdam, which offered both opportunity and a lifestyle that felt safer and more balanced than Brazil. I skipped deep dives into cost-of-living calculators or immigration policies at first. My focus was finding companies willing to sponsor my visa-a non-negotiable hurdle for relocating.&lt;/p&gt;

&lt;p&gt;As I started applying and getting responses from employers, I naturally dug deeper. I researched salaries on platforms like Glassdoor, checked healthcare systems, and even browsed posts from expats to get a feel for life in cities like Munich or Lisbon. But in the beginning, I let my desire for a better life guide me, keeping my planning lean to avoid paralysis by analysis.&lt;/p&gt;

&lt;p&gt;Looking back, a more detailed plan might have saved me some surprises-like underestimating rent in European cities. But taking action, even imperfectly, was the key to moving forward. If you’re considering a similar move, don’t let the quest for a perfect plan stop you. Start with a few clear priorities, and refine as you go. Try jotting down your own three must-haves today-what’s driving your relocation dream?&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation and Job Search: Getting Ready and Taking Action
&lt;/h2&gt;

&lt;p&gt;With Europe as my target and visa sponsorship as a non-negotiable, I rolled up my sleeves to prepare my application materials and dive into the job search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating My CV and Online Presence
&lt;/h3&gt;

&lt;p&gt;I knew a polished CV and LinkedIn profile were my first steps to catching recruiters’ eyes. I revamped both to focus on impact, not just duties. For example, I highlighted the number of requests that the system I worked had to support. These metrics showed employers what I could deliver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Targeting Companies That Sponsor Visas
&lt;/h3&gt;

&lt;p&gt;Next, I zeroed in on European companies offering visa sponsorship. I used LinkedIn’s job filters to find roles explicitly mentioning sponsorship and browsed boards like Relocate.me for tech jobs in Europe. I also checked Glassdoor for company reviews to gauge culture and work hours, ensuring I’d land somewhere that aligned with my goal of a balanced life. This targeted approach saved me from wasting time on roles that wouldn’t work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting Before Feeling Fully Prepared
&lt;/h3&gt;

&lt;p&gt;I’ll admit, I didn’t feel 100% ready for interviews, but I started applying anyway. Waiting for the “perfect moment” risked missing real opportunities. Since English isn’t my first language, those early interviews were nerve-wracking but invaluable. Each one helped me get comfortable explaining my experience and skills, like practicing a new codebase in real time. This learn-by-doing approach boosted my confidence, even if it meant a few rejections along the way. I know this strategy won’t suit every company-some have grueling, multi-stage hiring processes-but for me, jumping in early was the key to progress.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What’s one step you could take today to kickstart your own job search?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Handling Applications and Interviews: Learning as I Went
&lt;/h2&gt;

&lt;p&gt;Once I started applying, the relocation process felt real. Crafting applications demanded care, but interviews-especially in a second language-brought both challenges and growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Application Process
&lt;/h3&gt;

&lt;p&gt;For every job with a cover letter option, I seized the chance to stand out. I tailored each letter to the company’s mission or products, like when I connected my work on scalable APIs to a Berlin startup’s focus on seamless user experiences. This showed recruiters I’d done my homework and was eager to contribute. A personalized cover letter isn’t just a formality-it’s your chance to shine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interview Experiences
&lt;/h3&gt;

&lt;p&gt;All my interviews were in English, which wasn’t my first language. I sometimes stumbled over technical terms or missed nuances in questions, but most interviewers were patient, giving me space to clarify. Those early calls were like live coding sessions for communication: imperfect but invaluable. I learned you don’t need flawless English to succeed-just clarity and confidence.&lt;/p&gt;

&lt;p&gt;To prepare, I made daily study a habit, using LeetCode for algorithms and system design tutorials on YouTube. During interviews, I watched for cues like an interviewer’s nod or hesitation. If an answer fell flat, I noted it and adjusted my prep, focusing on weak spots like system design or explaining past projects concisely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning from Rejections
&lt;/h3&gt;

&lt;p&gt;Not every interview led to an offer. Rejections stung-especially one where I missed one simple JavaScript concept-but I treated them as feedback. I reviewed tough questions, like those on distributed systems, and practiced until I could answer confidently. Each rejection sharpened my skills and taught me to anticipate what employers valued, bringing me closer to my goal of a safer, balanced life in Europe.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What’s one interview question you’re nervous about? Try practicing it today!&lt;/p&gt;
&lt;/blockquote&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%2Fadint2smq3f8jq8vznfj.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.amazonaws.com%2Fuploads%2Farticles%2Fadint2smq3f8jq8vznfj.webp" alt="Photo by Pablo Heimplatz on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Receiving an Offer and Reflections
&lt;/h2&gt;

&lt;p&gt;After weeks of applications, interviews, and relentless studying, I received an offer from a fintech startup in Amsterdam. That moment was electric-a mix of excitement, relief, and pride. It wasn’t just a job; it was the key to a safer, more balanced life for my family.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Offer and What It Meant
&lt;/h3&gt;

&lt;p&gt;The email confirming the offer felt surreal. As someone who’d never worked abroad, knowing a European company valued my skills and would sponsor my visa was a game-changer. It meant I could finally plan my move, envisioning a future where my family could thrive without the daily safety concerns I faced in Brazil.&lt;/p&gt;

&lt;h3&gt;
  
  
  Looking Back on the Process
&lt;/h3&gt;

&lt;p&gt;As I celebrated, I reflected on how far I’d come. Beyond mastering algorithms and system design, I’d grown as a person-pushing through language barriers, adapting to tough interview questions, and bouncing back from rejections. Each step, even the painful ones, built my confidence and prepared me for the challenges of relocating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;p&gt;Here’s what I’d tell anyone chasing a job abroad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Before You’re Ready - Apply early, even if you’re nervous. My first shaky interview taught me to clarify questions upfront.&lt;/li&gt;
&lt;li&gt;Tailor Your Application - Craft cover letters that tie your skills to the company’s mission, like linking my API work to a startup’s goals.&lt;/li&gt;
&lt;li&gt;Use Interviews as Practice - Don’t let imperfect English stop you. Each call hones your communication, as I learned after stumbling through technical terms.&lt;/li&gt;
&lt;li&gt;Learn from Feedback - If an interviewer seems unimpressed, adjust. One rejection showed me I needed to brush up on distributed systems.&lt;/li&gt;
&lt;li&gt;Stay Persistent - Rejections hurt, but they’re progress. Each “no” refined my approach until I landed the offer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article is an overview of my experience getting a job abroad. If you’d like me to dive deeper into any specific part-such as how I studied, how I tracked my applications, how I organized my time while working full-time, or any other topic-please leave a comment! Your feedback will help me decide what to focus on in future articles.&lt;/p&gt;

&lt;p&gt;Your dream job abroad is within reach-start today!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>watercooler</category>
      <category>interview</category>
    </item>
    <item>
      <title>You Are Not Your Job: Reclaiming Your Identity as a Software Engineer</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Thu, 29 May 2025 15:26:33 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/you-are-not-your-job-reclaiming-your-identity-as-a-software-engineer-4c1k</link>
      <guid>https://dev.to/fabiothiroki/you-are-not-your-job-reclaiming-your-identity-as-a-software-engineer-4c1k</guid>
      <description>&lt;p&gt;&lt;strong&gt;Who are you?&lt;/strong&gt; If your first instinct is to say, “I’m a software engineer” or “I’m a developer,” I invite you to pause for a moment and dig a little deeper.&lt;/p&gt;

&lt;p&gt;That’s exactly where I found myself after graduating from university and landing my first job. For years, my goal was clear: get a degree, start a career. It felt like the default path — everyone around me was on it, and society cheered it on. But when I stepped into the working world as a software engineer, I felt unexpectedly lost. Without the structure of school or passions outside of work, I poured everything into my job. The long hours debugging code, learning new frameworks, and chasing deadlines became my identity. Climbing the career ladder seemed like the natural next step — after all, it’s what my parents did, and it’s what the tech world demanded. What could possibly go wrong?&lt;/p&gt;

&lt;p&gt;As it turned out, letting my job define me left me unfulfilled, disconnected from who I was outside of code, and questioning my purpose. This article is about my journey to reclaim my identity beyond my job title — and how you, too, can rediscover who you are outside the world of software engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Danger of Defining Yourself by Your Job
&lt;/h2&gt;

&lt;p&gt;It’s shockingly easy to let your job title become your identity, especially in software engineering. The tech industry thrives on celebrating promotions, shipped features, and GitHub commits as if they measure your worth as a person. Society piles on, too — say you work for a big-name tech company at a party or on X, and suddenly you’re “impressive.” I internalized that prestige, believing my value was tied to the company name on my LinkedIn profile.&lt;/p&gt;

&lt;p&gt;Early in my career, every bug I couldn’t crack or deadline I missed felt like a personal failure. I wasn’t just a software engineer who messed up — I was a failure. The pressure to prove myself, to keep up with new frameworks and maintain a “rockstar coder” image, was relentless. It took a toll on my mental health, leaving me exhausted and questioning my worth.&lt;/p&gt;

&lt;p&gt;Since my job was my only sense of purpose, I lost myself in it. I worked late nights, not out of passion but obligation, and spent weekends studying system design or tweaking side projects. Why not? My job gave my life meaning, so every moment had to serve it. I also craved validation from my manager and colleagues. Positive feedback was proof I was enough, but without it, I felt invisible. Negative feedback? That was worse — it felt like an attack on my very self, sparking shame and self-doubt.&lt;/p&gt;

&lt;p&gt;For a while, this mindset seemed to work. I was productive, earning promotions and delivering projects that won praise. But a few years in, despite climbing the career ladder, the cracks appeared. I grew demotivated, procrastinating on tasks I once loved. My energy tanked, and a quiet depression crept in. If my job was my reason for living, and it no longer sparked joy, what was left? That question was my wake-up call, pushing me to search for meaning beyond my role as a software engineer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you ever felt like a mistake at work was a reflection of your value as a person?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Recognizing the Need for Change
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Moment of Realization
&lt;/h3&gt;

&lt;p&gt;After a grueling week of chasing deadlines and obsessing over a bug I couldn’t fix, I stumbled across stoic philosophy through Marcus Aurelius’ Meditations. Its core idea hit hard: life is short, and no one will remember my commits or pull requests centuries from now. This truth was humbling yet liberating. Why was I pouring so much energy into feeding my ego through work, chasing likes on my LinkedIn profile or praise from my manager?&lt;/p&gt;

&lt;p&gt;Stoicism taught me I didn’t need to “make a dent in the universe,” as tech culture often demands. I couldn’t control if people accepted me or not, but I could control how I defined my worth. Letting go of the pressure to leave a grand legacy through my job freed me to focus on what truly mattered — my health, my relationships, and finding joy outside my role as a software engineer. This shift in mindset was just the beginning, pushing me to explore ways to live for myself, not my job title.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Struggles
&lt;/h3&gt;

&lt;p&gt;Shifting away from a work-centric identity was tougher than I expected. Most of my friends, fellow software engineers, lived for their jobs — side projects and open-source commits were their badges of honor. For them, work was life, and conversations rarely strayed from tech trends or career wins. When I started prioritizing balance, they noticed. A friend even asked why I’d stopped grinding on side projects, hinting I was “slacking.” Stoicism helped me shrug off their nudges to conform — I couldn’t control their opinions, only my choices.&lt;/p&gt;

&lt;p&gt;Redefining myself outside my job was scarier. If I wasn’t the coder chasing promotions, who was I? Evenings felt empty without Jira tickets or system design books. I felt lost, like I was rebuilding my identity from scratch. It was uncomfortable, but each small step — saying no to after-hours Slack or trying a new hobby — brought me closer to a life aligned with my true values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is your number one priority in life right now? Have you intentionally defined it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  First Steps Toward Change
&lt;/h3&gt;

&lt;p&gt;To break free from my work-obsessed routine, I started practicing sports — a simple way to escape the sedentary tech life and move my body. Stoicism taught me to focus on effort, not outcomes, so I didn’t pressure myself to be “good.” It was just a hobby to fill the hours I’d once spent debugging code past midnight.&lt;/p&gt;

&lt;p&gt;Weeks in, I found myself loving it. Each small improvement — running a bit farther, feeling stronger — brought a satisfaction unrelated to commits or promotions. This sense of progress, built through my own effort, was deeply rewarding. Running became a passion, waking me up with excitement for the next trail, not just the next sprint. Work remained important, but it no longer defined my days. Ironically, this new energy made coding feel less like a burden, letting me approach my job with a clearer, healthier mindset. Sports was just the start — other steps soon helped me build a fuller life beyond my job.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you couldn’t use your job title to describe yourself, what would you say?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  A New Identity
&lt;/h3&gt;

&lt;p&gt;Stepping back from defining myself by my job opened the door to rediscovering who I am. I’m no longer just a software engineer or a title on my LinkedIn profile. Guided by stoic principles to focus on what I can control, I prioritize health, relationships, and personal growth.&lt;/p&gt;

&lt;p&gt;I still find joy in programming — getting “in the zone,” squashing a tricky bug, or streamlining a workflow reminds me why I entered tech. But balance lets me tackle work with calm focus, not anxiety, making work more fulfilling. Sharing my story, as you’ve noticed, fuels my passion for helping others grow as humans, not just coders. I’ve learned personal growth drives professional success.&lt;/p&gt;

&lt;p&gt;Sports remains my stress reset, clearing my mind and sparking joy. Work is now just one part of a richer life, supporting my passions rather than defining me. I hope my journey inspires you to explore who you are beyond your job title.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways and Action Points
&lt;/h2&gt;

&lt;p&gt;Reflecting on my journey, I’ve learned that your job is just one part of who you are-not the whole story. When you tie your identity too closely to work, it’s easy to lose balance, feel burnt out, and question your self-worth. But it’s possible to redefine your relationship with work and reclaim your sense of self.&lt;/p&gt;

&lt;p&gt;Here are some key takeaways and practical steps you can start with today:&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You are more than your job title.&lt;/strong&gt; Your worth isn’t measured by your role, your productivity, or your achievements at work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External validation is natural but limited.&lt;/strong&gt; While positive feedback feels good, don’t let it define your self-esteem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Burnout often stems from blurred boundaries.&lt;/strong&gt; When work becomes your identity, setbacks hit harder and recovery takes longer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meaningful fulfillment comes from balance.&lt;/strong&gt; Investing in hobbies, relationships, and self-care fuels motivation and joy beyond the office.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Action Points
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set boundaries.&lt;/strong&gt; Create clear limits between work and personal time to protect your mental space. Turn off Slack notifications after work hours to protect your evenings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore new interests.&lt;/strong&gt; Try a hobby, sport, or creative activity that excites you without the pressure to “perform.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seek intrinsic motivation.&lt;/strong&gt; Focus on activities that bring joy and growth, not just external rewards or recognition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build a support system.&lt;/strong&gt; Surround yourself with people who value you for who you are, not just what you do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice self-compassion.&lt;/strong&gt; Be kind to yourself when things don’t go perfectly-your value isn’t tied to flawless performance. Forgive yourself for bugs or missed deadlines — your worth is deeper.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reclaiming your identity takes courage and time, but it leads to a healthier, happier life.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, please click the ❤️. Your feedback helps me understand what topics resonate with you and guides me on what to write next. Thank you for being part of this journey!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://thechilldev.substack.com/" rel="noopener noreferrer"&gt;Subscribe to my newsletter for more actionable advice to help you grow as a senior engineer — don’t miss out!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>mentalhealth</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Facing my performance anxiety</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Wed, 23 Oct 2024 20:03:55 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/facing-my-performance-anxiety-3o20</link>
      <guid>https://dev.to/fabiothiroki/facing-my-performance-anxiety-3o20</guid>
      <description>&lt;p&gt;&lt;em&gt;Have you ever felt your heart race and your voice falter just when you needed to speak up?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a software developer, I always thought my biggest challenges would be technical. Little did I know that my greatest obstacle would be the simple act of communication. I was gripped by an intense fear of judgment in meetings, one-on-ones, and workplace interactions. “Everyone struggles a bit, so I should be okay,” I’d tell myself, trying to normalize the anxiety that was slowly consuming my professional and personal life.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Signs
&lt;/h2&gt;

&lt;p&gt;My body betrayed me at every turn. My heart would race, breathing became difficult, and an overwhelming sense of stress and anxiety would wash over me. The most frustrating symptom was the feeling that my voice was stuck in my throat, making it nearly impossible to speak up.&lt;/p&gt;

&lt;p&gt;The anxiety didn't end when meetings did. I'd lie awake at night, replaying every conversation in my head. "Why did I say that during the meeting? They must think I'm so incompetent now," I'd berate myself, tossing and turning. &lt;/p&gt;

&lt;h2&gt;
  
  
  Facing the Facts
&lt;/h2&gt;

&lt;p&gt;I took multiple performance reviews and candid feedback to grasp the true cost of my silence fully. Each critique served as a mirror, reflecting how my communication struggles were hindering my progress. I began to see that my inability to articulate ideas was not just a personal hurdle; it was a barrier to career advancement and promotions.&lt;/p&gt;

&lt;p&gt;One particular feedback session with my manager stands out vividly in my memory. "Your technical skills are meeting our expectations," he said, "but given your expertise, you should be contributing more." He went on to explain that I needed to actively participate in the team's architectural discussions and confidently challenge technical decisions when I disagreed.&lt;/p&gt;

&lt;p&gt;This moment of realization was pivotal. It was as if a light had been switched on, illuminating the path I needed to take. I understood that if I wanted to grow in my career and personal life, I had to confront these challenges head-on. This revelation became the catalyst for change, pushing me to take action and seek solutions to improve my communication skills.&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%2Fhsat4c9tslki779qeorr.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.amazonaws.com%2Fuploads%2Farticles%2Fhsat4c9tslki779qeorr.jpg" alt="A motivational phrase: " width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking the First Step
&lt;/h2&gt;

&lt;p&gt;Acknowledging that I needed to improve was still challenging. As someone with performance anxiety, any hint of a skill that wasn't perfect felt like admitting complete failure. The mere thought of addressing my communication issues sent painful signals through my brain, urging me to retreat.&lt;/p&gt;

&lt;p&gt;Despite these internal alarms, I made a crucial decision: to ignore the discomfort and move forward. I knew that progress would come one step at a time, and I had to start somewhere&lt;/p&gt;

&lt;p&gt;Initially, I misdiagnosed my problem as a simple communication issue. I dove into books on public speaking and attended in-person courses, learning how to structure engaging presentations. While these skills were valuable, they didn't address the root of my anxiety&lt;/p&gt;

&lt;h2&gt;
  
  
  Exposure Therapy: A Turning Point
&lt;/h2&gt;

&lt;p&gt;I decided to challenge myself by giving technical presentations at work, starting with my team. Those first presentations were nerve-wracking, with anxiety building weeks in advance. But I had an unexpected ally: my colleagues. Their support during dry runs and their constructive feedback became my lifeline. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Big Test
&lt;/h2&gt;

&lt;p&gt;Emboldened by my progress, I set my sights on a larger goal: presenting to the engineers of the entire department. I spent over a week preparing, refining my slides, and conducting mental dry runs. The preparation was intense, but it paid off.&lt;/p&gt;

&lt;p&gt;The positive feedback I received from engineers across different teams was validating. This experience marked a turning point in my journey. Now, I even feel excited when I have to do public presentations. What once felt like a daunting task has transformed into something more enjoyable, albeit still challenging. The thrill of sharing my ideas and engaging with my audience adds a new dimension to the experience.&lt;/p&gt;

&lt;p&gt;While I still feel nervous during presentations, it's at a manageable level—I no longer feel like I'm "dying" on stage. Instead, I embrace the challenge as an opportunity for growth and connection. Now, I approach presentation opportunities with confidence, looking forward to each chance to share my knowledge and ideas.&lt;/p&gt;

&lt;p&gt;However, this victory was just the beginning. While I had conquered formal presentations, I realized that the root cause of my performance anxiety remained unaddressed. I still struggled in spontaneous situations, like team discussions about system design architecture, where there was no time to prepare. &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Looking back on my journey, I've learned some valuable lessons that I'd like to share with you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Power of Preparation: Thorough preparation for formal presentations is crucial. It not only helps engage your audience but also significantly boosts your confidence. Don't underestimate the impact of being well-prepared – it can be a game-changer in managing your anxiety.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Beyond Formal Presentations: While mastering prepared speeches is an important step, it's not the entire solution to conquering performance anxiety. The real challenge often lies in impromptu situations where you can't script your responses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continuous Growth: Overcoming anxiety is an ongoing process. Each presentation, each meeting, is an opportunity to learn and improve. Embrace these chances for growth, even when they feel uncomfortable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Deeper Work: Addressing the root cause of performance anxiety often requires more than just improving presentation skills. It may involve working on self-confidence, challenging negative thought patterns, or seeking professional help.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, while preparation is key for formal presentations, it's just one piece of the puzzle in overcoming performance anxiety. The journey to true confidence in all professional interactions is a longer, more nuanced path – one that we'll explore further in upcoming articles.&lt;/p&gt;

&lt;p&gt;If you're interested in learning more about overcoming anxiety in the tech workplace and fostering mindfulness in your career, I invite you to subscribe to the &lt;a href="https://thechilldev.substack.com" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://thechilldev.substack.com/p/true" rel="noopener noreferrer"&gt;Wan San Yip&lt;/a&gt; on &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://thechilldev.substack.com/p/true" rel="noopener noreferrer"&gt;the blowup&lt;/a&gt; on &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>anxiety</category>
      <category>mentalhealth</category>
      <category>career</category>
      <category>story</category>
    </item>
    <item>
      <title>Are You Feeling Overwhelmed? Recognizing Signs of Strain in Tech</title>
      <dc:creator>Fabio Hiroki</dc:creator>
      <pubDate>Tue, 08 Oct 2024 07:00:03 +0000</pubDate>
      <link>https://dev.to/fabiothiroki/are-you-feeling-overwhelmed-recognizing-signs-of-strain-in-tech-4164</link>
      <guid>https://dev.to/fabiothiroki/are-you-feeling-overwhelmed-recognizing-signs-of-strain-in-tech-4164</guid>
      <description>&lt;p&gt;In our fast-paced lives, distinguishing between typical stress and deeper mental struggles can be challenging. Often, we dismiss our feelings as mere reactions to everyday pressures, failing to recognize the underlying issues that can silently affect our well-being. These struggles may not always present themselves in obvious ways; instead, they can manifest subtly, leading us to believe that we are simply experiencing normal circumstances.&lt;/p&gt;

&lt;p&gt;To illustrate this complexity, we will explore the fictional story of Alex, a new software engineer. Through his journey, we will uncover how seemingly ordinary stress can evolve into significant mental health challenges that impact both personal and professional life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Alex: The New Software Engineer
&lt;/h2&gt;

&lt;p&gt;Alex had just landed his first job as a software engineer at an innovative tech startup. While he felt a rush of excitement, that thrill was quickly overshadowed by an overwhelming sense of anxiety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drowning in a Sea of New Information
&lt;/h2&gt;

&lt;p&gt;From day one, Alex found himself inundated with an enormous amount of new information. The codebase was vastly more complex than anything he had encountered in his studies or internships. Team meetings were filled with unfamiliar jargon and technical discussions that seemed to flow effortlessly among his colleagues.&lt;/p&gt;

&lt;p&gt;As the days passed, Alex's initial excitement gave way to a growing sense of self-doubt. He struggled to keep up with the rapid pace of learning required for his role. "How can I possibly learn all of this?" he wondered, feeling the weight of expectation on his shoulders.&lt;/p&gt;

&lt;p&gt;Alex couldn't shake the nagging feeling that he was falling behind. He began to question whether he was truly cut out for the job. "What if they realize I don't know as much as they thought I did when they hired me?" This thought plagued him, leading to sleepless nights and increased anxiety. Even when Alex completed tasks, he attributed his accomplishments to luck rather than skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Silent Struggle
&lt;/h2&gt;

&lt;p&gt;As Alex's self-doubt grew, he began to take drastic measures to prove his worth. He started working overtime. Weekends, once a time for relaxation and recharging, became extensions of his workweek. Alex convinced himself that if he put in more hours, he could catch up to his colleagues and prove his value to the company.&lt;/p&gt;

&lt;p&gt;This self-imposed overtime became Alex's coping mechanism. He reasoned that he could compensate for what he perceived as a lack of skill or knowledge by working longer hours. "If I just put in more time," he thought, "I'll eventually get to where I need to be."&lt;/p&gt;

&lt;h2&gt;
  
  
  Emotional Exhaustion
&lt;/h2&gt;

&lt;p&gt;As weeks turned into months, Alex's coping strategy began to backfire. The constant overtime and pressure he put on himself led to exhaustion. He found it increasingly difficult to engage with his work and colleagues. &lt;/p&gt;

&lt;p&gt;During a project meeting, the team celebrated a successful milestone, and while everyone around him was excited, Alex felt detached. Instead of sharing in the joy, he thought, “They’re celebrating, but I’m just trying to keep my head above water.” This feeling of isolation intensified his stress. &lt;/p&gt;

&lt;p&gt;In addition to emotional strain, Alex began experiencing physical symptoms. Fatigue became a constant companion, leaving him drained even after long work hours. He would find himself struggling to stay awake during meetings and needing an excessive amount of coffee just to get through the day. “If I just drink one more cup,” he thought, “I’ll be able to power through.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Reflecting on Our Journeys
&lt;/h2&gt;

&lt;p&gt;As we conclude Alex's journey, it's crucial to recognize that his experience isn't unique. Many of us navigate similar challenges in our careers, often in silence. The software engineering field, with its rapid pace and constant innovation, can be particularly demanding on mental health&lt;/p&gt;

&lt;p&gt;How often do we find ourselves overwhelmed by expectations, questioning our abilities, or feeling isolated despite being surrounded by colleagues? &lt;/p&gt;

&lt;p&gt;Recognizing these struggles is the first step toward addressing them. Remember, you’re not alone—many share these experiences.&lt;/p&gt;

&lt;p&gt;In future articles, we'll explore practical solutions and strategies to help support mental health and foster resilience in the workplace. We'll delve into topics such as managing impostor syndrome, preventing burnout, and creating a supportive work culture prioritizing mental well-being. &lt;/p&gt;

&lt;p&gt;If you want to learn more about navigating these challenges and fostering a healthier work environment, I invite you to subscribe to my &lt;a href="https://thechilldev.substack.com/" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;. Together, we can work towards understanding, growth, and a more supportive tech industry. &lt;/p&gt;

&lt;p&gt;Let's break the silence around mental health in tech. Your story matters, and your well-being is crucial. Join me on this journey towards a more open, supportive, and mentally healthy workplace.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@silverkblack?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Vitaly Gariev&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-man-sitting-in-front-of-a-laptop-computer-l1LsokOV0-s?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mentalhealth</category>
      <category>career</category>
      <category>anxiety</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
