Six architectural patterns Emre has put into production, what each one is for, and the engagement where it was applied.
The role Emre states on his CV is a claim about judgement rather than about tools,
so this page is written to be checked rather than believed: six patterns he has put
into production, what each one actually buys, and a link to the engagement where it
was used. The drawings are the argument; the links are the evidence.
Every heading below names a decision with a cost attached. None of them is a
preference about style, and each is answerable — a reader who disagrees can open the
engagement and see what was built.
Functional core, imperative shell
Decision logic is pure and side effects sit at the edges. The core computes what should happen and can be tested without a database, a network or a clock; the shell is the only place anything actually happens.
This is not a preference about style. It is what makes a system's behaviour reproducible: the same inputs give the same decision every time, and the parts that can fail are pushed to a boundary where failure is expected and handled.
An agent that plans, acts and observes will loop. The question an architect has to answer is what stops it — so the loop is bounded by a retry ceiling, each outward call sits behind a circuit breaker, and runs that die mid-flight are recovered rather than left orphaned.
Nothing commits without passing a human gate. The gate is not a notification; it is a state the run stops in and stays in until a person approves or refuses.
An outbox, so the agent edge reads committed facts
The business row and the event that announces it are written in one transaction. A relay then publishes what has committed, and the agent layer consumes from the topic.
The failure this prevents is subtle and expensive: an agent reacting to a row that was written and then rolled back, or reacting to a table mid-write. Reading from the log means the agent only ever sees what actually happened.
Tenancy enforced by the database, not by the caller
One table, one connection, and a row-level policy the database applies to every query. Application code cannot forget to add the tenant filter, because the filter is not in application code.
The alternative — a WHERE clause every developer must remember — is one missed clause away from a cross-tenant read, and in an occupational health and safety system that is somebody's medical record.
A model call is checked before it runs and judged after. A budget check can refuse the call outright; the response is scored by a heuristic and by a model acting as judge; and every stage emits into one telemetry spine.
That gives three different guarantees, and it is worth naming which is which. The breaker is what catches a failure, the budget is what caps it, and the trace is what makes it explainable afterwards.
The interesting constraint is the network that is not there. A client loses signal mid-action, keeps acting, and everything it did has to arrive in the order it was done once the connection returns.
So the client talks to a queue rather than to the API, and the queue is what replays. Order is the whole contract: a move applied out of sequence is a different game.