Daeseon Yoo

Production case films

Five production problems, shown as engineering decisions

Five incidents and redesigns from manufacturing systems. Each film keeps the sequence short: context, failure, decision, change, and the recorded result.

01

Transaction boundary

Case 01 · Don't let ERP roll back the factory

MES↔ERP integration - transactional-outbox redesign at SK AX

SETUP
MES — factory floor
ERP — finance
ONE transaction
local tx — commits instantly
🏭Final processproduct discharged
⚙️MES Appcompletion save
🗄️Completion recordMES DB
📥Staging rowPENDING → SENT/FAIL
🤖Batch workerown schedule · retry ≤3
🧾ERPcost posting
floor ✓ done · system ✗ missing

“An external system's failure must not roll back my system's core state.”

→ cut the transaction boundary in two

LOT number = idempotency key
🧑‍💻me · backend
🧑‍🔬DBA
👷floor operator
🧑‍💼ERP manager

Final production step: the product is physically completed and discharged. MES records the event; ERP posts the cost.

02

Change surface

Case 02 · The middleware that knew too much

46 endpoints → 1 reflection-based gateway — mobile WMS at SK AX

SETUP
Factory floor
Legacy C# — IIS
📟PDA · 15 screensscan / move / save
🧱Tomcat middlewarebetween floor and legacy
🗃️WMS serviceC# .NET
🗃️Other servicesshared server
46 one-to-one APIs
legacy change → redeploy ×8 sites
1 common API · reflection: key → class/method
new legacy API = zero middleware change

“The middleware should forward requests — not know the business.”

→ one common API · dispatch by reflection at runtime

🧑‍💻me · junior
🧔senior engineer
🧑‍🔧team of 3

Mobile WMS at an EV battery factory: PDA screens → Tomcat middleware → legacy C# services. Three engineers for all of it.

03

Payload and freshness

Case 03 · Send the key, not the truck

HTTP 413 on mobile scans → PK-only payloads - batch 30 → 80

SETUP
Floor — PDA
Shared legacy server
📟PDA batch savefull LOT objects
🚧middlewareforwards
🗄️Legacy C# servershared · other services live here
📚DBsource of truth
plant code + LOT no. only
fresh read at save time

just raise the shared server's payload limit

“Send identifiers, not state — the DB is the source of truth.”

don't push your risk onto a shared server

👷operator
🧑‍💼customer
🧑‍💻me · backend

Operators scan LOTs on PDAs and save in batches. The save travels through middleware to a legacy C# server — SHARED with other services.

04

Concurrency

Case 04 · Two servers, one number

Duplicate LOT IDs across instances → Oracle FOR UPDATE, scoped and shrunk

SETUP
MES instances
Oracle
🖥️Server Aread seq
🖥️Server Bread seq (same ms)
🔢counter row · todaycurrent_seq = 1042
🔒 row lock — today's row only
B queued: waits statement + commit, not the app round-trip

“Serialize at the row, and hold the lock for a statement — not a conversation.”

FOR UPDATE on one row → refined to atomic UPDATE … RETURNING

Multiple MES instances generate date-based LOT IDs from ONE shared counter row in the database.

05

Delivery flow

Case 05 · Rebuilding trust, then the query

Costing project: single-intake anchor + 7.7K-line PL/SQL → per-process CTEs

SETUP
Customer · 4 staff
Devs · 6 + PM
🧑‍💼staff 1
🧑‍💼staff 2
🧑‍💼staff 3
🧑‍💼staff 4
🧑‍💻dev 1·2
🧑‍💻dev 3·4
🧑‍💻dev 5·6
random requests · no priority · no focus
7.7K linesone PL/SQL · nested CASE · dead legacy branches
validated with the customer before every change · ~1 month
🧑‍💻me · tech lead (single intake)
🗂️prioritized queuecontext attached
🖥️self-service pagestaging · limited permission

“The bottleneck isn't the code — it's that nobody anchors the two sides.”

listen first → single intake → context with every assignment → then fix the code

Six months into a costing project, trust is broken: delivery arguments, a replaced lead. I join as tech lead — and listen to both sides first.