Reference
Accept-Language
LinkedIn

Adis Fetibegović,
.NET backend engineer.

Six years on production .NET systems, continuously since 2020. I build ASP.NET Core services, author the shared .NET platform a set of services sits on, and move old systems to modern .NET without a rewrite. This page is my CV, written as the thing I spend my days on: an API reference.

Executed, not proposed

  • mediator library -> in-house CQRS abstraction
  • one message bus -> another, live
  • SQL Server -> PostgreSQL

All three on systems that stayed in service the whole time. No maintenance weekend, no big-bang cutover.

Engineer
Adis Fetibegović

.NET backend engineer. Enschede, Netherlands.

adis_0411@hotmail.com
Track record

Six years on production .NET systems, continuously since 2020, at four Dutch engineering and software firms: MyPoi World, Sigmax, Tauw and Strukton Systems.

BSc Computer Science, Saxion. PSM I (Scrum.org, 2023).

How to read this

GET /v1/engineer

Every section is an endpoint. The profile and the employment history come first, then the three kinds of work I do, then the stack, the integrations and the conventions, all of it taken from what I have actually shipped.

Request GET
$ curl \
    https://sanaengineering.net/v1/engineer \
    -H "Accept: application/json"
Response 200 OK
content-type: application/json
x-engineer: adis-fetibegovic
{
  "engineer": "Adis Fetibegović",
  "title": "Senior .NET Backend Developer",
  "experience_years": 6,
  "based_in": "Enschede, Netherlands",
  "specialisations": [
    "ASP.NET Core services & API contracts",
    "Reusable .NET platform & libraries",
    "Legacy modernisation & platform migrations"
  ],
  "certifications": [
        "PSM I, Scrum.org, 2023"
  ],
  "languages": ["nl", "bs", "en", "de"],
  "contact": "adis_0411@hotmail.com"
}
application/json11 fields

GET /v1/engineer

Who I am, and the parts of it you can check for yourself.

I'm a versatile and experienced .NET backend engineer with a BSc in Computer Science and a Professional Scrum Master certification. What I'm good at is designing, building and maintaining scalable backend solutions in the Microsoft .NET ecosystem: robust systems, APIs, databases, and the integrations that modern applications actually rest on.

In practice that comes down to three things. Backend architecture on a boundary the build enforces. The shared library platform underneath a set of services. And the migrations that move an estate from one platform generation to the next. I also work across TypeScript/Angular, WPF and mobile with Xamarin and MAUI, enough to fit into a multidisciplinary team and talk to the people either side of the API. But the backend is where my focus and my strongest expertise sit, and I'd rather say that plainly than take on a front-end someone else would do better.

Response
FieldValue
full_nameAdis Fetibegović
based_inEnschede, Netherlands.
experience6 years on production .NET systems, continuously since 2020.
domainsFreight and logistics: orders, carriers, senders, locations, driver assignment, digital freight documents. Public-transport ticketing: fares, combi-tickets, discounts, timetables, real-time vehicle feeds. Subscription and planning models. Geospatial querying.
educationBSc Computer Science (Informatica), Saxion University of Applied Sciences.
certificationsAZ-204 Developing Solutions for Microsoft Azure. Passed Sep 2023. Microsoft retired the certification in 2026.
Professional Scrum Master I (PSM I). Scrum.org, Feb 2023.
languagesDutch and Bosnian natively, English and German at full professional level. Requirements, standups and handover documents in any of them.
Employment history, Software Developer
CompanyPeriod
MyPoi World B.V.Apr 2024 - present · Hengelo
SigmaxMar 2022 - Mar 2024 · Enschede
Tauw NederlandFeb 2021 - Feb 2022 · Deventer
Strukton SystemsJan 2020 - Jan 2021 · Hengelo

Previous and current employers. Client and project names belong to those companies, so they are not mine to publish.

POST /v1/apis

Design and build ASP.NET Core services, and own the contract everyone else generates against.

Vertical-slice feature modules on a clean four-layer boundary: API to Application to Domain, with persistence implementing the application's contracts and nothing leaking back the other way. CQRS with validation pipelines and typed results, rather than exceptions used as control flow. Thin controllers, sealed handlers, records for every DTO. And a rich domain layer, so entities, value objects, domain events and business invariants stay out of the transport and persistence code.

The boundary is held by the build, not by a code review. Architecture test suites fail CI on layer, naming or visibility violations, so the design is still the design a year later, whoever happens to be working on it by then. Decisions get recorded as ADRs, with diagrams generated from the codebase instead of drawn once and left to rot.

The OpenAPI specification is generated from the service, linted in CI, and published as the single source of truth for whichever teams generate clients against it. That includes versioning and breaking-change discipline, plus separate specs per consumer surface when one API serves more than one kind of client.

Response delivers
{
  "api": "ASP.NET Core",
  "delivers": [
    "Vertical-slice modules, four-layer boundary",
    "CQRS, validation pipeline, typed results",
    "Rich domain: entities, value objects, events",
    "EF Core on PostgreSQL or SQL Server",
    "OpenAPI spec, linted and versioned in CI",
    "Architecture tests that fail the build",
    "Integration tests on real DB and broker",
    "ADRs with generated diagrams"
  ],
  "boundary_enforced_by": "the build",
  "runs_in": "the team's repository and pipeline"
}

POST /v1/platform

Authoring the shared .NET platform a set of services stands on, so each one stops reinventing it.

Any organisation past its second service has the same quiet problem. Each one solved validation, caching, auth, audit and persistence a little differently, and now none of it can be changed. The answer is an internal platform rather than a wiki page: a CQRS abstraction, a validation pipeline, EF Core and spatial persistence integration, identity-provider integration, mail, storage, localisation. Published as versioned packages with changelogs on the organisation's own registry, so a project mounts a capability instead of copying it.

It ships with an architecture-test kit, so a service that takes the platform inherits the rules that keep it coherent. And with a template repository, so a new service starts standardised instead of being standardised later. Drop-in feature modules (feature flags, users, AI chat) arrive with migrations for every database the platform supports.

This is the work I have done most of, and the work I see offered least. Four services with four different ways of validating a request is the situation it exists for.

Response delivers
{
  "distribution": "Versioned NuGet packages",
  "packages": [
    "CQRS abstraction & validation pipeline",
    "EF Core + spatial persistence integration",
    "Identity-provider integration",
    "Mail, storage, localisation, caching"
  ],
  "comes_with": [
    "Reusable architecture-test kit",
    "Drop-in feature modules with migrations",
    "Changelogs on an in-house registry"
  ],
  "projects_mount_not_copy": true,
  "published_to": "an in-house registry and CI"
}

PATCH /v1/legacy

Move an old estate to modern .NET incrementally. PATCH, not PUT. The platform pieces get replaced one at a time.

A rewrite sounds like the decisive answer. It's also the one that most often runs long and lands late. The alternative is unglamorous: put a façade in front of the old application, move one bounded slice at a time behind it, and keep both halves shippable at every step. Every migration has a slice you can move this month and a slice you shouldn't touch for a year. The first job is telling them apart.

I work both ends of the age range at once. A .NET Framework 4.7.2 codebase on EF6 and MSBuild in one window, greenfield modern .NET in the other. And I've executed platform-wide migrations, not just proposed them. A mediator library replaced by an in-house CQRS abstraction. One message bus swapped for another. SQL Server moved to PostgreSQL. All of it on systems that stayed in service throughout.

Response delivers
{
  "strategy": "strangler fig, slice by slice",
  "steps": [
    "Tests that pin down current behaviour",
    "Reverse-proxy façade in front of the old host",
    "Port one bounded slice to modern .NET",
    "Shift traffic, verify, repeat",
    "Retire the old host last"
  ],
  "big_bang_cutover": false,
  "shippable_at_every_step": true
}

GET /v1/stack

Accepted values, by key, taken from what I have actually shipped rather than a wish list. If something is not here, I have not put it into production.

runtime
.NET 10.NET 9C#.NET Framework 4.7.2
architecture
Vertical sliceClean ArchitectureCQRSDomain eventsValue objectsADRs
web
ASP.NET CoreRESTful APIsOpenAPIMVCWCF
data
PostgreSQLEF CoreSQL ServerGeospatial (PostGIS)EF6Audit trailsDeterministic seeding
messaging
RabbitMQWolverineWorker servicesMassTransit Migrated a production system from one broker library to another while it stayed live.
identity
Auth0JWTPolicy-based authzIdentityServer3
testing
xUnitArchitecture testsReal-container integration testsNSubstituteMockQueryableFluentValidationQuality gates
delivery
DockerDocker ComposeGitLab CI/CDnginxPrivate NuGet registryPre-commit gatesSerilogGrafana Loki
cloud
Azure The platform work I've delivered is self-hosted and containerised: PostgreSQL, RabbitMQ, Docker Compose, nginx, GitLab CI. That transfers directly, but I'd rather say so plainly than imply years of delivered Azure.
ai tooling
Claude CodeMCPAI review agentsSlice scaffolding Engineering workflow, committed and human-reviewed. See GET /ai-tooling. OpenAI as a product feature sits under GET /integrations instead.
beyond the backend
TypeScriptAngularWPFXamarin / MAUIImage processing (OpenCV, ImageSharp) Real but secondary. Enough to work inside a multidisciplinary team, but not where my strongest work sits.

GET /v1/integrations

Third-party systems already integrated, and the pattern every one of them is built to.

Each integration is a Contracts project plus a swappable provider implementation. The vendor is replaceable, the provider is mockable in tests, and no piece of business logic ever learns the vendor's name. That pattern matters more than the list below. The list is what I have already done. The pattern is what carries over to whatever comes next.

payments
MolliePay.nlIntersolve (loyalty)Unipay (hardware) Including a physical hardware gateway and loyalty-card balances, not only card payments.
logistics
PTV (routing & ETA)Collect&Go eCMR
public transport
Bison KV6/KV17NETEX import Dutch national real-time and timetable standards.
identity
Auth0 + Management APIIdentityServer3 (legacy)
messaging
Twilio SMSMandrill
ai & storage
OpenAIPrevider object storage
erp
Nubix ERP

GET /v1/practice

The things held in place by machinery rather than by good intentions.

Standards written in a document decay the week after they're written. Standards a pipeline refuses to merge don't. Everything below fails a build instead of appearing as a comment on a pull request, and that's the only version of a standard that survives a busy quarter and a change of staff.

architecturearch tests

Architecture test suites fail the build on layer, naming and visibility violations. The four-layer boundary isn't a convention, it's a test.

contractsspec lint

OpenAPI generated from source, linted in CI, versioned deliberately. A breaking change is a decision, never an accident.

qualityquality gate

Static-analysis quality gates on every repository, warnings treated as errors so the build stays clean, and pre-commit gates so the obvious never reaches review.

testsCI

Unit tests with substitutes and generated fixtures. Integration tests that stand up a real database and a real message broker in containers, reset between tests, with real tokens. Dedicated base classes for HTTP, in-process eventing and broker round-trip tiers.

decisionsADR + review

Architecture decisions recorded as ADRs, with diagrams generated from the codebase instead of drawn once and left to go stale.

dataupdater app

Migrations applied by a dedicated updater application, never implicitly at startup. Soft-delete filters, audit trails that also cover bulk update paths, and deterministic seeding for development and test.

operabilityruntime

Structured logging shipped to a queryable store, third-party call tracing through request-logging middleware, and automated database backups. When it breaks at 02:00, someone can find out why.

Response CI
$ git push && # the pipeline decides

ok build            warnings = errors
ok architecture     layers, naming
ok unit             substitutes
ok integration      real db + broker
ok spec lint        openapi
ok quality gate     static analysis

{ "merge": true }

GET /v1/ai-tooling

AI-assisted engineering, committed to the repository as tooling, so a team's standards outlive the people who set them.

Alongside the architecture tests and the CI gates, I check a team's conventions in as tooling that actually runs. Concretely: Claude Code skills that scaffold a complete vertical slice (entity, database configuration, migration, commands, queries, controller) already conforming to the architecture. Specialised AI review agents for architecture, query performance, correctness and test quality. Path-scoped rule files. And MCP server definitions versioned alongside the code they serve.

The point isn't novelty, and it isn't that AI writes the code. It's that a new developer's first pull request looks like the codebase's tenth, and a reviewer's attention goes to the domain instead of to layer violations and naming. A generated slice is a starting point a human then owns, and every one of those agents produces a recommendation a person accepts or rejects.

Most of this is easier to show than to describe, so it is the part I would rather walk through in a repository than write down. It is also the clearest example of a wider habit: I would rather encode a convention once than repeat it in twenty reviews.

Response in the repository
{
  "committed_tooling": [
    "Claude Code skills: slice scaffolding",
    "AI review agents (architecture, tests)",
    "Path-scoped convention rules",
    "MCP server definitions, in-repo"
  ],
  "generated_slice": [
    "entity", "configuration",
    "migration", "commands",
    "queries", "controller"
  ],
  "reviewed_by_a_human": true
}