When I began tracing complaints scattered across many modules, I realised they all pointed to the same root: there was no transaction-identity foundation anyone could trust. This is how I built one from the ground up.

Each exercises a different muscle from the flagship — giving non-technical teams room to move without losing control, and maturing a feature through iteration grounded in real learning.

⚠️All product names, figures, and metrics in this portfolio are fictional or illustrative and created for demonstration. The case studies show how I think about product — problem framing, state machines, governance, research — without containing confidential information from any real project ⚠️

selfservice | governance | RBAC

provenance | sync | migration

I wanted branches to design their own forms without waiting on an engineering release — but without losing governance. So I designed the builder with review-approval, access control per-role and per-branch, and publishing.


THE PROBLEM

Every form was hardcoded. Adding a single form meant going through the engineering cycle — slow, expensive, and unscalable across hundreds of branches.


KEY DECISIONS

Governance from the start, not later · published forms are immutable · reorder with buttons first, drag-drop deferred.







I shipped this feature, then matured it based on how people actually used it. From re-typing data by hand, to syncing automatically from the source — with provenance and safe migration.


ITERATION



In v1, documents could be created — but people had to re-type data that already existed. In v2, the data is pulled automatically, with the right rules.


KEY DECISION

Dedicated columns, not JSON, so it’s queryable · a snapshot that preserves manual curation across re-syncs · a source of truth I marked explicitly for engineering.


SAFE MIGRATION

Backfill first, then enforce the constraint · dry-run in staging · log every failed record for manual review.


At first glance, the system looked fine. Teams kept processing transactions, invoices kept going out. But once I looked closer, a different story emerged: every module managed its own transaction identity, billing was created manually and easily lost, and cancelling a payment meant deleting data. Four problems that seemed unrelated were, in reality, rooted in the same thing.

As I mapped the complaints, four patterns kept recurring — and every one of them chipped away at trust in the system.

  1. No central identity. Teams couldn’t refer to “the same transaction” consistently; coordination happened manually and was prone to mis-linking.

  2. Billing not tied to transactions. Invoices were created by hand, easily duplicated or lost, and hard to reconcile.

  3. Multi-source payment unsupported. Real scenarios — a deposit, then credit, then final settlement — didn’t fit in a single account.

  4. Unsafe cancellation. Cancelling meant deleting data, and the audit trail disappeared with it.

Foundation first, features later

I separated transaction identity into its own release, before building billing on top. This delayed user-visible features — but prevented far more expensive technical debt down the line. I made the trade-off deliberately and communicated it to stakeholders.

Auto-generate, not manual entry

Document numbers and billing accounts are system-generated and can’t be overridden. I removed a source of human error, at the cost of a flexibility that — once I looked into it — turned out not to be needed.

Reversal, not delete

Cancelling creates a new correction transaction rather than removing the old one. It’s harder to implement, but it’s non-negotiable if I want the system to be financially trustworthy.

Explicit payment priority

I set the order in which the balance is reduced — deposit first, then credit — so the calculation stays deterministic and auditable, not dependent on interpretation.

Rather than patching each issue one by one, I wanted a foundation that closed all four at once.

  1. One transaction identity, consistent across every module.

  2. A billing account generated automatically for each order, with no manual step.

  3. Staged payment from multiple sources within a single account.

  4. Cancellation with dual authorization and a permanent audit trail.

THE PROBLEM

KEY DECISION AND TRADE_OFF

WHAT I SET OUT TO DO

I build the foundations systems rely on.

product and development

Five things that always show up.

Whether I’m working on billing, transaction identity, or user research, my approach tends to return to the same five things. This is the thread that best describes how I think.

how i work

core product

supporting modules

v1 re-typing —>

v2 auto sync

Systems thinking

Strict state machines

Governance & RBAC

Scope discipline

Safe releases

Three trust failures, one shared consequence: members and studios stop relying on the platform.

I model the transaction lifecycle explicitly, so system behaviour stays predictable and auditable.


Access per-role and per-branch, review-approval flows, and dual authorization for anything sensitive.


I’m firm about what ships and what doesn’t. Complexity is deferred deliberately, not forgotten.


Risk registers, phased migration strategy, and concurrency handling — so change doesn’t break what already works.


01

02

03

04

05

Order and billing engine

Two other stories: governance and iteration.

Custom Document Builder

Document Generation

One order as the source of truth.

~40%

try it live

try it live

need sample of my PRD document? click below~

ps: need my real PRD document? please contact me through my email —> amalliayova.ardina@gmail.com

~90%

0

1:1

reduction in cashier reconciliation time


drop in lost/duplicate billing incidents


of cases were early-morning classes

billing account per order, automatic


  1. Parent Order as the source of truth; every document must link to one Order ID.

  2. Automatic numbering per document, with a daily sequence per branch and atomic increment so numbers never collide.

  3. State machine: OPEN → PAID (soft lock) → CLOSED (hard lock); reversal PAID → OPEN only while no closing exists.

  4. Dual authorization for reversal: requester and approver are separate, a reason is required, and the audit trail is permanent.

Because this touches money, I mapped the failure modes up front rather than waiting for them to happen.

  1. Two operators processing the same bill → locked with a “processing” status + session control.

  2. Double reversal on one payment → a payment can only be reversed once.

  3. Number collision under high traffic → atomic increment at the database level.

  4. Duplicate orders from a race condition → unique constraint + database transaction.

THE SOLUTION

RISK I ANTICIPATED

~2 weeks → ~1 day · time for a new form to go live

~60% · reduction in document creation time

Most of my work isn’t about adding new features. When I look closely at a product, the problems that surface most often live in a layer people rarely see: transaction identity, billing, and data governance. That’s where I work — building a backbone teams and branches can actually trust.

product manager
b2b platform

Create a free website with Framer, the website builder loved by startups, designers and agencies.