AI Made Me Faster. It Also Exposed What I Didn't Understand
DEV Community

AI Made Me Faster. It Also Exposed What I Didn't Understand

Faster Fixes, Deeper Understanding

There was a point while building Security Lens when I realized I was fixing problems faster than I could explain them. The error disappeared. The application started. Deployment worked. Great. Then I looked at the configuration I had just changed and thought: Wait. Why did that actually work? That happened more than once. AI helped me move faster while building the project. So did documentation, Stack Overflow, GitHub issues, and a lot of searching. But the faster I could get an answer, the easier it became to accept a working fix before I had built a mental model of what was happening. A few small configuration problems made that painfully obvious.

1. server.port=${PORT:8080}

I used this while deploying my Spring Boot application to Railway.

server.port=${PORT:8080}

At first, my understanding was basically: Railway needs this. I changed the configuration. The server started. Problem solved. Except I couldn't really explain the line.

  • What is PORT?
  • Who sets it?
  • Why is 8080 still there?
  • Why does the same application use 8080 locally but something else after deployment?

Once I stopped treating the line as magic, it became much simpler.

  • PORT is an environment variable.
  • Railway provides a port to the running application.
  • Spring Boot reads that value.
  • If PORT is not available, 8080 becomes the fallback.

Local machine: PORT does not exist → Spring Boot uses 8080
Railway: Railway provides PORT → Spring Boot uses that value

The configuration wasn't really about Railway. It was about letting the environment decide something that should not be hardcoded. That was a much more useful thing to understand.

2. 8081:8080 was not just two random ports

Docker gave me a similar moment. I was running something like:

docker run -p 8081:8080 ...

Two ports. Both looked like ports. I knew the command worked. But for a while my knowledge was basically: Use this and the container becomes accessible. That wasn't enough.

  • The first port belongs to the host.
  • The second belongs to the container.
localhost:8081   ← Host port 8081
               ← Container port 8080
               ← Spring Boot application

So: 8081:8080 → HOST:CONTAINER

Once I understood that, another thing started making more sense. localhost is not one universal place. localhost from my PC means my PC. localhost from inside a container means that container. That sounds obvious after you understand it. It was not obvious when I was simply copying commands until something connected.

3. Ollama wasn't broken. Port 11434 was already being used

Another time, I tried to run:

ollama serve

and got an error because port 11434 was already in use. My first reaction was basically: Why isn't Ollama starting? So I restarted things. Tried the command again. Still failed. Eventually the more useful question became: What is already using port 11434?

That changed the way I looked at the problem. Ollama normally runs its local server on port 11434. If something is already listening there, another process cannot simply bind to the same address and port.

The problem was not necessarily: Ollama is broken
It was:

Process A ← already owns :11434
Process B ← tries to use :11434
            ↓ conflict

The error message had been telling me something fairly specific. I just wasn't reading it at the right level yet.

4. Environment variables were not just a deployment trick

The same thing happened when I started handling API keys. Putting a value directly into application.properties is easy. It also works. Something like this is much better:

openai.api.key=${OPENAI_API_KEY}

Initially, I thought of environment variables mostly as another thing I needed for deployment. Then I realized several concerns were connected here.

  • The application needs configuration.
  • Different environments may need different values.
  • Secrets should not be committed to the repository.
  • The source code should not need to change just because the application moves from my machine to another environment.

So this:

Application code + Environment‑specific configuration

started making much more sense than:

Application code + Whatever values happen to be hardcoded on my machine

Again, the syntax itself wasn't difficult. The part I had been missing was the reason the boundary existed.

The AI Paradox

AI was genuinely useful during all of this. I could paste an error. Ask what was wrong. Get a configuration example. Change the code. Try again. That made development much faster.

But it also created an interesting problem. Sometimes the answer arrived before the understanding did. There is a big difference between:

  • I have a fix.
  • I understand what changed.

AI made the first one much faster. It did not automatically give me the second one. I still had to trace the environment, the process, the port, the configuration source, or the network boundary myself.

And I don't think the solution is to stop using AI. I definitely don't want to go back to doing everything slowly just to prove that I can. Instead, I'm trying to add one small step after certain fixes. When something starts working, I ask:

  • Who provided this value?
  • Which environment does this address or port belong to?
  • What exactly would break if I removed this configuration?

I don't do this for every error. Sometimes I just need to fix something and keep building. But if the same concept keeps appearing - ports, environment variables, localhost, processes, configuration - I try not to leave it at: It works now.

Reflective Practice

Writing about the problem exposed the gap. The funny thing is that I noticed many of these gaps while writing development notes. While coding, this felt sufficient:

Error → Search → Change configuration → Works → Next

Writing about it forced me into another step:

Error → Search → Change configuration → Works → Why?

That's where I realized I couldn't clearly explain some of the fixes I had already used. So I went back. I looked at how Railway provides its port. I looked again at Docker port mapping. I checked which process was using 11434. I thought more carefully about why configuration and secrets were coming from the environment.

None of these were huge discoveries. But they started connecting. And that connection feels more valuable than memorizing another command.

Security Lens Project

Most of these examples came from building and deploying Security Lens, a Spring Boot project that analyzes images and documents for privacy risks using OCR, EXIF metadata, rule‑based detection, and an AI‑assisted explanation layer. The project gave me a reason to touch deployment, containers, external services, configuration, and AI integration in one place. Apparently it also gave me several opportunities to discover things I thought I understood.

I documented the architecture, implementation decisions, and what I learned in the public case study:

-> Security Lens - Technical Case Study on GitHub

Continuing the Journey

AI is still making me faster. I just don't want to confuse faster problem solving with deeper understanding. For now, when an error disappears, I'm trying to leave myself one last question:

Why did it disappear?

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.