DEV Community

CodeWithIshwar
CodeWithIshwar

Posted on

# Backend Engineers Learning AI: The Fundamentals Still Matter

I've spent years working with backend systems.

APIs, databases, caching, integrations, performance, authentication, cloud infrastructure — these are the kinds of problems that become familiar after you've been building software for a while.

Recently, I've been spending more time learning another side of software engineering:

LLMs, RAG, AI Agents, tool calling, and MCP.

At first, it felt like entering a completely different world.

New terminology.

New frameworks.

New architectural patterns.

And honestly, it made me feel like a beginner again.

But the deeper I went, the more I noticed something interesting:

AI engineering has a lot more backend engineering in it than I initially expected.


The Traditional Backend Mental Model

A simplified backend architecture might look like:

Client
   ↓
API
   ↓
Business Logic
   ↓
Database
   ↓
Cache / External Services
Enter fullscreen mode Exit fullscreen mode

Of course, production systems have much more around this:

  • Authentication
  • Authorization
  • Logging
  • Monitoring
  • Queues
  • Caching
  • Load balancing
  • Rate limiting
  • Distributed systems
  • Cloud infrastructure

But the general flow is deterministic.

The application receives a request.

Our code decides what happens.

The application returns a response.

Then we add AI.


Adding an LLM Looks Easy

The first architecture is surprisingly simple:

User
  ↓
API
  ↓
LLM
  ↓
Response
Enter fullscreen mode Exit fullscreen mode

Send a prompt.

Get a response.

Done.

For a prototype, this can be enough.

But production applications rarely stay this simple.

Suppose we're building an assistant that answers questions using internal company documents.

Now we need retrieval.


Enter RAG

A simplified Retrieval-Augmented Generation pipeline might look like:

Documents
   ↓
Chunking
   ↓
Embeddings
   ↓
Vector Database
Enter fullscreen mode Exit fullscreen mode

Then, when the user asks a question:

User Question
      ↓
Embedding
      ↓
Vector Search
      ↓
Relevant Documents
      ↓
Context
      ↓
LLM
      ↓
Answer
Enter fullscreen mode Exit fullscreen mode

Conceptually, this is easy to understand.

But implementing it properly raises a lot of questions.

How should we chunk documents?

A fixed number of characters?

Tokens?

Paragraphs?

Sections?

Semantic boundaries?

Chunking affects retrieval quality, context quality, token usage, and ultimately the quality of the answer.

How much context should we retrieve?

More context doesn't automatically mean a better answer.

Irrelevant context can introduce noise.

How do we evaluate retrieval?

This is an important distinction:

Similar Document ≠ Correct Document
Enter fullscreen mode Exit fullscreen mode

Vector similarity gives us mathematically similar content.

It doesn't guarantee that the retrieved information is actually the best information for answering the user's question.

This is where techniques such as hybrid retrieval and re-ranking become interesting.

And suddenly RAG isn't simply:

LLM + Vector Database.

It becomes an information-retrieval and system-design problem.


Production RAG Is a Backend System

Imagine an enterprise knowledge assistant.

A real request might travel through something like:

User
 ↓
Authentication
 ↓
API
 ↓
Authorization
 ↓
Query Processing
 ↓
Retrieval
 ↓
Permission Filtering
 ↓
Re-ranking
 ↓
Context Construction
 ↓
LLM
 ↓
Output Validation
 ↓
Logging
 ↓
Response
Enter fullscreen mode Exit fullscreen mode

Look at that architecture again.

Most of it isn't an LLM.

It's backend engineering.

The LLM is an important component inside a larger system.


Agents Make Things Even More Interesting

RAG mainly helps models access information.

Agents introduce the ability to take actions.

Suppose our application provides these tools:

get_customer()

find_order()

check_delivery_status()

create_support_ticket()

send_email()
Enter fullscreen mode Exit fullscreen mode

Now the user asks:

"My order hasn't arrived. Can you find out what happened?"

An agent might execute:

Understand Request
       ↓
Find Customer
       ↓
Find Order
       ↓
Check Delivery
       ↓
Analyze Result
       ↓
Decide Next Action
       ↓
Respond
Enter fullscreen mode Exit fullscreen mode

That's powerful.

But it introduces another set of engineering problems.


What Happens When the Agent Is Wrong?

This is where my backend brain immediately starts asking questions.

What happens if the agent chooses the wrong tool?

What happens if it sends incorrect arguments?

What happens if the external API times out?

Should the agent retry?

How many times?

What happens if it enters a loop?

Should every tool be available to every user?

Which operations require confirmation?

Should an AI agent be allowed to delete something?

How do we audit the actions it performed?

How do we reproduce a failure?

These aren't primarily prompt-engineering questions.

They're software-engineering questions.


Tool Calling Needs Security Boundaries

Imagine an agent with these capabilities:

read_customer()
update_customer()
issue_refund()
delete_customer()
Enter fullscreen mode Exit fullscreen mode

Giving all four tools to an agent without proper controls would obviously be dangerous.

We still need authorization.

Conceptually:

User
 ↓
Authentication
 ↓
Authorization
 ↓
Agent
 ↓
Allowed Tools
 ↓
Tool Execution
Enter fullscreen mode Exit fullscreen mode

And tool arguments should be validated just like any other API input.

For example, if you're using Python, structured validation can sit between the model and the actual operation:

from pydantic import BaseModel, Field


class RefundRequest(BaseModel):
    order_id: str
    amount: float = Field(gt=0)
    reason: str
Enter fullscreen mode Exit fullscreen mode

The model proposing an action shouldn't automatically mean that action is trusted.

That's a principle backend engineers already understand:

Never trust external input.

An LLM should be treated with similar caution.


MCP Adds Another Layer

I've also been exploring Model Context Protocol (MCP).

AI applications increasingly need access to external systems:

AI Application
   ├── Files
   ├── Databases
   ├── GitHub
   ├── Search
   ├── Internal APIs
   └── Development Tools
Enter fullscreen mode Exit fullscreen mode

Building custom integration logic for every combination can become difficult.

MCP provides a standardized approach for exposing tools and context to AI applications.

Conceptually:

AI Application
      ↓
  MCP Client
      ↓
  MCP Servers
  ├── Files
  ├── Database
  ├── GitHub
  └── Internal Tools
Enter fullscreen mode Exit fullscreen mode

I'm still exploring MCP, but I find the broader idea interesting:

standardizing how AI applications interact with external capabilities.


Reliability Still Matters

Suppose your AI application depends on an external model provider.

What happens when that provider fails?

A production architecture might eventually need:

Request
   ↓
Primary Model
   ↓
Success? ─── Yes → Response
   │
   No
   ↓
Retry / Fallback
   ↓
Alternative Model
Enter fullscreen mode Exit fullscreen mode

Then we have the usual distributed-system questions:

How many retries?

What timeout?

Should we use exponential backoff?

Can the operation safely be retried?

What should happen if every provider fails?

Again, these are familiar backend problems.


Caching Becomes Interesting Too

LLM applications can be expensive.

So caching becomes another useful area to think about.

Depending on the application, we might cache:

Embeddings
Retrieval Results
Document Processing
Model Responses
Tool Results
Enter fullscreen mode Exit fullscreen mode

But each layer has different invalidation requirements.

For example:

If a source document changes, should the cached retrieval result still be trusted?

Probably not.

And now we're back to one of the oldest jokes in computer science:

Cache invalidation is hard.

AI didn't fix that either. 😄


Observability Needs to Evolve

For traditional backend applications, we monitor things like:

Request Latency
Error Rate
CPU
Memory
Database Queries
API Calls
Enter fullscreen mode Exit fullscreen mode

AI applications introduce additional signals:

Token Usage
LLM Latency
Retrieval Latency
Retrieved Documents
Tool Calls
Agent Steps
Model Errors
Cost per Request
Response Quality
Enter fullscreen mode Exit fullscreen mode

If a user reports:

"The assistant gave me the wrong answer."

We need to know why.

Was retrieval wrong?

Was the correct document retrieved but ignored?

Was the prompt constructed incorrectly?

Did the model hallucinate?

Did an external tool return incorrect data?

Without observability, debugging AI applications becomes guesswork.


Python Is Connecting Both Worlds for Me

One reason I've been spending more time with Python is that it sits naturally between backend engineering and AI development.

For backend:

Python
 ↓
FastAPI
 ↓
Pydantic
 ↓
PostgreSQL
 ↓
REST APIs
Enter fullscreen mode Exit fullscreen mode

For AI:

Python
 ↓
LLMs
 ↓
Embeddings
 ↓
Vector Databases
 ↓
RAG
 ↓
Agents
Enter fullscreen mode Exit fullscreen mode

And eventually:

Backend Engineering
        +
AI Engineering
        +
System Design
        ↓
Production AI Applications
Enter fullscreen mode Exit fullscreen mode

That's the intersection I'm currently exploring.


Don't Start With Agents

One thing I'm increasingly convinced about:

If you're a backend engineer starting with AI, don't immediately jump into complicated multi-agent systems.

Start smaller.

A learning path that makes more sense to me is:

LLM API
   ↓
Structured Output
   ↓
Embeddings
   ↓
Vector Search
   ↓
Basic RAG
   ↓
RAG Evaluation
   ↓
Tool Calling
   ↓
Single Agent
   ↓
Agent Workflows
   ↓
MCP
Enter fullscreen mode Exit fullscreen mode

At every stage, build something.

Don't just watch tutorials.

For example:

Project 1

Build a simple FastAPI endpoint that calls an LLM.

Project 2

Add structured output and Pydantic validation.

Project 3

Build semantic search over documents.

Project 4

Turn it into a RAG application.

Project 5

Add retrieval evaluation.

Project 6

Give the model one safe tool.

Project 7

Build a multi-step workflow.

Project 8

Experiment with MCP.

This way, every new abstraction solves a problem you've already experienced.


What I'm Learning From All of This

When I started exploring AI engineering, part of me wondered:

Do backend engineers eventually need to become AI engineers?

I'm starting to think that's not quite the right question.

The boundary between the two may simply become less important.

Backend engineers already know how to build systems.

AI introduces new components into those systems.

APIs
Databases
Caching
Queues
Cloud
Security
Observability
        +
LLMs
Embeddings
RAG
Agents
Tools
MCP
Enter fullscreen mode Exit fullscreen mode

Together, they create a new generation of software applications.


Final Thought

AI has made me feel like a beginner again.

But I've realized something important:

I'm not starting from zero.

Years of understanding APIs, databases, debugging, performance, security, and system design don't disappear when you start learning AI.

They become the foundation.

Building an LLM demo is relatively easy.

Building an AI application that is:

  • Reliable
  • Secure
  • Observable
  • Scalable
  • Maintainable
  • Cost-efficient

is still an engineering challenge.

And that's the part I'm most interested in exploring.

Learn → Build → Break → Debug → Understand → Improve → Repeat. 🔁

If you're a backend engineer currently learning AI, I'd love to hear your experience:

Which backend skill has helped you the most while building AI applications?

Top comments (0)