Photo of Božidar Vulićević

Hi, I'm Bo.

Božidar Vulićević

I'm a Staff Backend Engineer from Montenegro with 10 years of experience. I build and evolve the systems behind products, and stay close to them in production.

  • TypeScript
  • Node.js
  • Python
  • PostgreSQL
  • Kubernetes
  • AWS

I work remotely with teams in European time zones.

At a glance Get in touch

Selected work

Two projects worth a closer look.

Multi-tenancy for a running product

client onboarding
1 week to ~5 min
tenants
50 to 1,000+
infrastructure cost
−30%

A mature ad-tech SaaS product ran a separate cluster for every client. I designed the move to one shared cluster, with shared components and a tenant layer developers rarely have to think about.

The change reached across teams, which required close alignment while the product kept running.

An API for store-aware ads

stores in one campaign
100K+
for partner integrations
API-driven

We built the backend of an ad creation platform as a small team, and I led its design. Ads are composed through the API from reusable components, so partners can build them from their own systems.

Each ad adapts to the store closest to the viewer and shows products that store carries, ranked by engagement.

How I work

It starts with a person and a problem

Before there's code, there's a problem someone cares about. My first job is to understand what's actually happening, who it affects, and what we still don't know.

I try to get back to first principles before deciding what the solution should look like.

Good software starts with a shared understanding.

Draw it before building it

Then we make the problem visible, with whoever needs to be part of it. Sometimes that's an EventStorming session. Sometimes it's a quick sketch, diagram, or documentation we can return to later.

Domain-driven design helps create shared language and clear boundaries. Nobody should leave with a different picture in their head.

An hour at the whiteboard is cheaper than weeks of building the wrong thing.

Behind the sketch, a system

Services, data, events and integrations, plus the people and processes around them.

I want my mental model to match how the system actually behaves: what it depends on, where it's constrained, and where there's room to evolve.

Real systems carry history. Understanding it matters when deciding where the system goes next.

The workbench

Then I build. This is the tooling I use most often, next to the job each one does.

TypeScript, Node.js and Python
Services and tooling the next person can read and change.
PostgreSQL
Data that has to stay correct.
Events and messaging
Services talk through events, so one slow part can fail without taking the rest down.
Containers and Kubernetes
The same thing, running the same way, everywhere.
AWS
Infrastructure written as code and reviewed like code.
Git
Small commits, with messages that explain why.
A coding agent
Research, debugging and first drafts, faster than I can alone.

The list will change. The reasons for picking each tool change much more slowly.

An agent on the bench

There's a coding agent on the workbench too. I use Pi, a small terminal agent I've shaped around how I work.

I use it to explore codebases, research APIs, debug problems, challenge ideas, and verify fixes. It makes the loop from question to evidence much faster.

In the driver's seat

I drive and the agent accelerates.

It brings speed and breadth. I bring context: the system's history, what the product needs, and the decisions we've already made.

The decisions that matter get written down and shared.

The agent and the model will change. Who's driving doesn't.

Looking after the system

Shipping is one part of a system's life. I stay close to it in production and adapt it as the product evolves.

I want the system to make sense to the people who work on it next: where its boundaries are, why things work the way they do, and who owns what.

That means boundaries that match the product, owners you can find, and alerts that fire for a reason. As our understanding grows, I refactor and remove old parts instead of working around them one more time.

Listen, measure, learn

Then we find out whether it worked.

Feedback comes from users, product, engineers, and from the system itself through metrics, traces, and logs.

  1. Understand
  2. Build
  3. Learn
  4. Understand again

Short feedback loops help us adjust quickly and keep what we're building aligned with reality.

When the workday ends

At the end of the day, my laptop closes. The systems keep running.

I step away, reset, and come back ready for the next iteration.

If you'd like to work together or have a conversation, I'd be glad to hear from you.