Software & IoT Engineer · Nonthaburi, Thailand

Natawat
Damrongsilp

I build systems that go into production and stay there.

A telecommunication engineer who writes software. Eight production systems for government, education and healthcare clients — and, running underneath them, the layer most application developers leave to someone else: MQTT brokers, device credentials, TLS termination, multi-tenant isolation at the transport layer, and ESP32 firmware talking to all of it.

Natawat Damrongsilp
Focus
IoT & networking · Backend · AI systems
Currently
Freelance / contract engineer
Studying
M.Eng. ICT — AIT (GPA 3.79)
Foundation
B.Eng. Telecommunication Eng.
Certification
ISC2 Certified in Cybersecurity

About

I'm a freelance software engineer near Bangkok, taking client systems from requirements through architecture, implementation, deployment and handover. Most of my work is systems other people's jobs depend on — a clinic's daily reconciliation, a school's ticket queue, an officer's screening decision.

My foundation is telecommunication engineering, and it still decides what I reach for first. On the IoT platform I enforced tenant isolation at the MQTT broker with per-device mountpoints rather than filtering in application code, verified device credentials through the broker's own auth hook, and terminated TLS at the edge for both HTTPS and MQTT-over-WebSocket. I'll write the ESP32 firmware that publishes the telemetry as readily as the service that consumes it — and I'm comfortable at the layer below both: protocols, ports, certificates, and what is actually on the wire.

I came to it from the other end. Two years at Toyota Tsusho NEXTY Electronics testing embedded automotive software taught me what a system looks like when someone else's safety case depends on it, and building the test tooling for it is why I still write the verification script before I call something delivered.

That context is what shaped how I build. When a system's output informs a decision about a person, "the model said so" is not an answer. So I tend to choose the auditable version: a rule-based router over an LLM one, reviewed query templates over generated SQL, policy rules weighted above a learned model, medians over means, and an explicit account of what a number does not prove.

I also try to be the first person to find the flaw in my own work — the strongest thing in this portfolio is a result I retracted, because finding the leak in your own training split is worth more than the score it was inflating.

Open to IoT, networking, backend, AI-systems and platform roles. The fastest way to reach me is email.

Experience

  • Freelance Software Engineer Jul 2026 – present · independent / contract Lead engineer on client delivery — requirements, architecture, implementation, deployment and handover. Eight production systems for government, education and healthcare clients.
  • Software Engineer — Toyota Tsusho NEXTY Electronics (Thailand) Jul 2023 – Aug 2025 Software testing and validation for embedded automotive systems. Built automated test tooling in Python and VBA, and designed simulation environments for embedded verification.

Education

  • M.Eng. Information & Communication Technology Asian Institute of Technology · Aug 2025 – present Currently studying. GPA 3.79.
  • B.Eng. Telecommunication Engineering KMUTNB · Jun 2019 – May 2023 GPAX 3.33, second-class honours. Senior project: full-stack IoT dashboard, ESP32 to web.

Also

  • ISC2 Certified in Cybersecurity (CC) May 2026 – Apr 2029 Paired with hands-on vulnerability-assessment tooling.
  • Languages Thai (native) · English (intermediate, TOEIC 620) · Japanese (JLPT N4). Several systems here ship bilingual Thai/English.

Stack

What I reach for, roughly in order of how much production time I have on it.

Languages

Python · TypeScript / JavaScript · C · C++ · SQL · VHDL · PHP · VBA · Bash

IoT & networking

MQTT · EMQX (rule engine, HTTP auth hooks, per-device mountpoint isolation) · MQTT-over-WebSocket · TLS termination · reverse proxies (Caddy, Nginx) · TCP/IP and network protocols · port scanning and service fingerprinting · time-series telemetry ingestion

Embedded

ESP32 · NodeMCU · Arduino · Raspberry Pi · PlatformIO · FPGA · VHDL · C / C++ firmware · embedded test tooling and system simulation

Backend

FastAPI · Next.js API routes · Django REST · Node · JWT & OIDC / SSO auth · Zod · Prisma · Drizzle · SQLAlchemy · Mongoose · REST / OpenAPI

Frontend

React 19 · Next.js App Router · Tailwind · shadcn/ui · Redux Toolkit · React Query · Recharts · i18n (TH/EN)

Data

PostgreSQL · MongoDB · ClickHouse · Redis · ChromaDB · MySQL · SQLite · Neon · Firestore · pandas · scikit-learn · XGBoost

AI systems

RAG pipelines · local embeddings (bge-m3) · vLLM / OpenAI-compatible serving · NL-to-SQL · evaluation benchmarks · LLM-as-judge scoring

Platform

Docker & Compose · Kubernetes (Kustomize) · GitLab CI/CD · Caddy · Nginx · AWS EC2 · Vercel · Linux server administration

Quality

pytest against real databases · Playwright · end-to-end verification scripts · business-cycle smoke tests · UAT design · LLM benchmark and judge-based evaluation · automated test tooling (Python, VBA) · system simulation · leakage audits · usability evaluation

AI-assisted development

Agentic coding workflows · Claude Code (CLI) · AGENTS.md / CLAUDE.md conventions · AI-driven code review

Selected work

Fifteen projects, most of them shipped to real users. Open any card for the engineering detail — the decisions worth defending, not a feature list. Filter by the kind of role you're hiring for.

01

Bilingual RAG + NL-to-SQL assistant for immigration officers

In production
Client system · government agency · ~9,500 LOC · AWS EC2
Client code — not publishedArchitecture case study →

One chat interface answering two unrelated classes of question, in Thai or English: statistical queries against ~10.85 million passenger records, and procedural questions about an official operations manual.

FastAPIReact 19ClickHouse PostgreSQLRedisChromaDB vLLM · Llama 4bge-m3Caddy
Engineering detail

What I built

  • A rule-based router, deliberately not an LLM one. A keyword/regex scorer weighs a policy score against a statistics score over bilingual keyword lists, with hard-coded fast paths, across three answer patterns: SQL statistics, policy retrieval, and ephemeral per-session document Q&A. Cheaper, faster, and auditable — and a SQL route can re-route itself to retrieval when it finds no statistical signal.
  • NL-to-SQL through hand-written templates. An intent classifier produces ~40 named intents, each mapped to a reviewed ClickHouse query. Free-form LLM SQL was off the table: a government system cannot risk a hallucinated query against live records.
  • Retrieval that decomposes. Complex scenario questions split into up to five sub-topics, retrieved separately, then de-duplicated, over a local embedding model — no document text leaves the host.
  • Two separate follow-up mechanisms. Parameter inheritance for statistics ("what about China?" reuses the previous intent) and scenario enrichment for policy questions, both over a Redis context with a 30-minute TTL.
  • A memory-poisoning guard. Prior SQL statistics are stripped from the model's message window on retrieval routes, so passenger numbers cannot bleed into a procedural answer.
  • Honest refusal. Citation verification and relevance-gated retrieval, so the assistant declines rather than fabricates.
  • Production hardening. JWT auth, OTP email verification, PDPA-compliant audit logging, Docker Compose, Caddy TLS.
  • Measured, not asserted. A 92-question bilingual benchmark: 98.9% routing accuracy, 91.3–95.7% judge-verified answer correctness.
"The interesting decision was refusing to let the LLM write SQL. For a government system, an auditable rule-based router into reviewed query templates beats a smarter but unverifiable agent — and I have a 92-question benchmark showing the router hits 98.9%."
02

Passenger risk-scoring system

Decision support
Client system · immigration checkpoints · ~13,400 LOC · 10.85M training records

A hybrid 0–100 risk score for inbound passenger screening that an officer can read the reasons for. A rule engine, a gradient-boosted model and an anomaly signal, fused and banded into a recommended action — with a human always in the loop.

PythonXGBoostpandas FastAPIDocker
Engineering detail

The engineering that matters

  • Rules weighted above the model on purpose — 0.50 rules / 0.30 ML / 0.20 anomaly. The model predicts a narrow document-violation proxy; the rules carry actual screening policy. Defending that weighting is the core of the design.
  • Hard overrides and soft floors. Expired visa, watchlist hit or prior deportation force the top band regardless of score; certain profiles set a floor. A statistical model should not be able to talk a system out of a categorical rule.
  • Leakage-safe training across five source systems. GroupKFold on passport number, 5-fold — a random split lets the model memorise passengers who appear on many flight legs.
  • Rule-generated labels excluded from training. Training a model on labels the rules produced is circular, and the resulting score would just be the rules wearing a hat.
  • ~1% positive class handled honestly: keep every positive, sub-sample negatives, scale the positive weight. No SMOTE — synthetic passengers inflate metrics without improving real detection.
  • Explainable output — score, band, which rules fired, the hard-override list, and the recommended officer action.
"The most valuable thing I did was retract my own result. An F1 of 0.98 looked great until I realised a random split was leaking the same passenger across train and test — one person has many flight legs. GroupKFold on passport number gave an honest number, and I can explain exactly why the honest number is the useful one."
03

Enterprise IoT platform — broker to browser

50 commits · public
AIT

Real-time telemetry ingestion, device management and dashboard visualisation — including the C++ firmware that publishes the telemetry and the Kubernetes manifests that run what receives it.

EMQX · MQTTNext.jsTypeScript PostgreSQL · PrismaMongoDBKubernetes ESP32 · C++GitLab CI
Engineering detail

What I built

  • Multi-tenancy enforced at the transport layer. Mountpoint isolation per device and group in the MQTT broker, so one tenant's devices physically cannot publish into another's topics — rather than filtering it out in application code afterwards.
  • Device credentials verified through the broker's HTTP auth hook against an internal endpoint, using a three-part credential model.
  • Polyglot persistence chosen per access pattern: PostgreSQL + Prisma for users, devices, groups and projects; MongoDB for time-series telemetry and dashboard configs. Two stores because the read patterns genuinely differ, not by default.
  • Broker rule-engine forwarding into the application backend, with Nginx terminating TLS for both HTTPS app traffic and MQTT-over-WebSocket.
  • Deployment both ways — Docker Compose for development, Kubernetes with Kustomize for the platform, behind a GitLab CI/CD pipeline.
"It's the full vertical — I wrote the C++ that publishes the telemetry and the Kubernetes manifests that run the thing that receives it. The part I'd defend hardest is mountpoint isolation at the broker: multi-tenancy enforced at the transport layer, not by application filtering."
04

Aesthetic clinic ERP

In production
Client system · clinic group · ~14,400 LOC · 172 files · 17 collections

A complete bilingual clinic ERP: booking, OPD, sub-unit stock deduction, course packages, finance and HR. The business logic is the hard part — this is a system where the inventory and the money have to agree at the end of every day.

Next.js 16React 19MongoDB · Mongoose Redux Toolkiti18n TH/ENDocker
Engineering detail

What I built

  • "Close case" as a single transactional trigger. One action fires five steps — FIFO stock deduction, bottle usage update, course visit count, commission generation, queue completion. Concentrating it in one service is what keeps the money and the inventory consistent.
  • FIFO with real lot costing. Already-opened bottles are consumed before new ones, earlier-expiring lots first, and the cost recorded is the actual cost of the deducted lot — not a moving average that quietly launders margin.
  • Double-booking prevented at the API layer, blocking both room and practitioner overlap even across different rooms, so a second client cannot bypass it.
  • Book-before-registration. Bookings can exist before a patient has a hospital number; the system back-links it when the case is first opened. Reception should never have to invent data to make the software proceed.
  • Multi-branch data model with per-branch catalogues, owner-sees-all / staff-see-their-own visibility, and patient records shared across the chain.
  • Role-based access for six roles, enforced at the API rather than by hiding buttons.
  • A 27-step smoke test walking the entire business cycle: instalment course sale → booking with overlap protection → registration → OPD → mandatory measurement → separately-billed add-on → case close → finance and permissions.
  • Usability-driven iteration. A formal HCI evaluation scored it 58/100; I shipped a remediation round — async button states, toasts, route guards, Buddhist-era dates, global search, status legends.
"The decision I'm proudest of is making 'close case' the single trigger for everything financial. Five things have to happen together — stock, bottles, course counts, commissions, queue state. Spreading that across the UI is how clinics end up with inventory that doesn't match the money."
05

HRIS with org-chart-routed approvals

Delivered
Client system · international school · ~7,000 LOC · 70 files
Client code — not published

Employee self-service for leave, entitlements, overtime and attendance, with a supervisor approval workflow routed by the organisation chart rather than by a hard-coded list of approver names — all behind single sign-on.

Next.js 16TypeScriptPostgreSQL 16 Prisma 6Auth.js v5 · OIDCTailwind v4 shadcn/uiDocker Compose
Engineering detail

What I built

  • Built to the brief's three foundations in dependency order — organisation chart, then HR master data, then SSO. Approvals derive from the chart, so a reporting-line change reroutes every pending and future approval automatically.
  • Pluggable OIDC SSO. Google Workspace is wired; Microsoft Entra or any generic OIDC provider drops into the same seam. First sign-in links the SSO identity to the employee record by email.
  • A dev-login escape hatch that cannot ship. Gated behind an environment flag and forced off in production, so the app is demoable without an identity provider but cannot be deployed insecurely.
  • Seeded role-based demo data so the client could evaluate the actual workflow without a setup session.
  • One-command deployment. Compose brings up Postgres, applies migrations, seeds and serves, with host ports remapped to avoid collisions on the client's machine.
"Approvals route off the organisation chart, not a list of approver names. When someone changes manager, HR changes one edge in the chart and every pending and future approval follows — no config, no migration."
06

Service desk — department routing and rotation assignment

In production
Client system · international school · ~12,800 LOC · 97 files · 24 API routes

Staff report a problem, it reaches the right department, and a named person is accountable for fixing it. Raise → triage → assign → accept → hold, transfer or outsource → close → rate, with the workflow around that lifecycle editable by the school's own administrator.

Next.js 14TypeScriptMongoDB React QueryZodJWT + Google OIDC PlaywrightCaddy
Engineering detail

Routing, and where configuration should stop

  • Split out of the room-booking codebase as its own system, on the customer's instruction that an event and a job request are different things. Separate repo, container, database and release cycle; they share exactly one value — a signing secret — so someone signed in to one is recognised by the other. No workflow crosses between them.
  • Tickets go to a department's central inbox, never fanned out to everyone in it. A dispatcher assigns from that one queue. Broadcasting to a whole team means nobody owns the job.
  • Assignment by rotation, and it explains itself. Fewest open jobs → longest waiting → name, so an even queue is a plain A → B → C but it self-corrects for someone on leave or already holding four jobs. The rotation writes its reasoning into the ticket history, and a dispatcher can always override — which is what you want when a fault comes back and should return to whoever fixed it last time.
  • "Accept" is a timestamp, not a new status. A status records where a ticket is, never when it got there, and a second name for one state adds a case to every site that switches on status. By that same test, "outsourced" genuinely is a status — and deliberately not a transfer, because a vendor has no queue and nobody who signs in, so the job stays with the technician who has to chase it.
  • Two KPI clocks, reported as medians. Assigned→accepted and accepted→closed, per department, team and person. Medians because one laptop left at a repairer over the holidays makes a mean useless; every figure carries the count it was drawn from; per-person figures group by who accepted the job so a later reassignment can't credit the wrong name. It also surfaces the two things a ticket-derived report hides — jobs never accepted, and technicians with no jobs at all.
  • Technicians on leave stay visible — greyed, labelled, still selectable, skipped by the rotation. A dispatcher who sees four names where there were five can't tell whether someone is away or the roster is wrong.
  • The school owns its configuration; I own the state machine. Statuses and their transition table stay in code because the code reasons about them by name. Everything around it is theirs: SLA hours, which endings must be explained, what each status and priority is called, which events send mail, what a requester must fill in. Written up as a 32-item master-data audit where every "keep in code" line has to state a real reason, with additive, version-stamped config migrations so a school that has already tuned a setting keeps it.
  • The bug class this project taught me to grep for: a constant that becomes configurable has to be read from the configuration everywhere it is enforced or displayed. A setting that only changes the settings page is worse than no setting, because the administrator believes it worked.
  • Mail with an outbox. A dependency-free SMTP client records every notification before delivery is attempted, so while a department still has no mailbox its messages accumulate as "skipped" rather than vanishing.
  • Tests grown from 3 to 85 over five weeks — and the suite went from 30 seconds to under one once I stopped the pure access-rule module from importing the config layer, which was opening a database connection just by being imported.
  • A 34-case UAT driven through the real application with Playwright across five personas: 29 pass, 3 fail, 2 not exercisable without real elapsed time. Every screenshot a real screen, every "disabled" judgement read off the actual DOM rather than the picture.
"The line I had to defend was which parts of the workflow the customer owns. They asked to edit the flow themselves, and the right answer was not 'here is a drag-and-drop state machine' — the code reasons about statuses by name, so an arbitrary graph would have given them a system that quietly stopped notifying and reporting. The skeleton stays mine; what it's called, how fast it must move, what must be explained and who hears about it are theirs."

Built twice

An earlier FastAPI + React version implemented the same planning notes as one system combining tickets and room booking. The delivered system went the other way — two systems, separate databases, sharing only a signing secret. Two honest answers to "when do you split a system out, and what does sharing a codebase actually cost?"

07

Team planner — Gantt + Kanban workspace

Public repo
~19,200 LOC

A full-stack rebuild of a single-file localStorage HTML planner into a real multi-user product backed by PostgreSQL — the same Gantt and Kanban workspace, but a whole team shares one board and nothing is lost when a browser is cleared.

Next.js 16React 19Prisma 7 PostgreSQL 17Tailwind v4Docker
Engineering detail

Deployment decisions worth mentioning

  • A three-service Compose with a dedicated migrate service that applies migrations, bootstraps admin accounts, then exits before the app starts — ordered startup, not a race.
  • Bootstrap passwords from environment variables, never committed.
  • Postgres bound to localhost on the production host, so the database is not internet-reachable.
  • An rsync + ssh redeploy that deliberately excludes the server's own environment file — the most common way a deploy script destroys production config.
"Migrating a localStorage prototype to Postgres is the moment a demo becomes software — you suddenly own identity, concurrency, migrations and backups."
08

Clinic income & expense dashboard

Live
Client system · ~8,300 LOC · 82 files · deployed on Vercel
Client code — not published

Replaces a clinic's summary spreadsheet with a real application: daily visit entry with patient autocomplete, line items, split payments, expense entry with daily cash closeout, monthly per-day × payment-method reports with CSV export, and a KPI dashboard.

Next.js 16Drizzle ORMPostgreSQL Auth.jsnext-intlRechartsVercel
Engineering detail

The migration path is the project

  • A CSV importer for the old spreadsheet's daily tabs, with preview-then-confirm and idempotent re-import — re-importing a date replaces it rather than doubling it.
  • Verified by an end-to-end script that runs the real sheet export through the production code path and asserts every aggregate matches the sheet's own totals: day totals, per-method sums, report rows and dashboard rows.
  • That is how you earn a client's trust when you replace the system they have been reconciling by hand for years. The migration is not "done" when the data loads; it is done when their numbers and your numbers agree.
09

School website with a custom CMS

Delivered
Client system · ~17,600 LOC · 135 files · 30+ content sections

A full public school website — admissions, curriculum, athletics, news, calendar, staff, tuition — with a bespoke database-backed CMS so staff edit every page without a developer. Authenticated admin area, file uploads, Excel export.

Next.js 16PrismaNextAuth ZodexceljsDocker
Engineering detail

Worth mentioning as client-facing delivery at scale: 30+ routes and a bespoke CMS data model, not a template with the colours changed. The interesting constraint was designing a content model general enough for thirty structurally different sections while still giving each editor a form that looks like the page they are editing.

10

Customer retention decision support system

10 commits · public

Predicts subscriber churn, scores risk, quantifies revenue at risk and simulates retention strategies — a full ETL → prepare → model → dashboard pipeline, reproducible with one command.

Pythonscikit-learnXGBoost PostgreSQLStreamlitDockerMake
Engineering detail

The credibility detail: it ships a leakage audit and calibration alongside the model comparison — baselines plus logistic regression, decision tree, random forest and XGBoost with cross-validated metrics — and the README states plainly that the dataset is synthetic and roughly balanced, so this is a methodology demonstration and not a claim about any real company.

Stating your own limitations is what separates a data-science project from a screenshot of a good score.

11

Tournament management — built twice, two architectures

Two repos
Live scoring · bracket generation · leaderboards · role-based admin

The same product implemented two ways: once with a separate FastAPI backend and split containers, then collapsed into a unified full-stack Next.js application.

FastAPINext.jsFirebase Auth FirestoreMermaid docs
Engineering detail

Google OAuth with Admin-SDK token verification, Google Sheets import, and Firestore persistence. Both repositories document their architecture with Mermaid diagrams — a component graph and a request sequence.

Why it's worth mentioning: it is a direct, concrete answer to "when would you split a backend out versus keep it in the framework?" — not an opinion, but two working implementations and the cost of each.

12

Event photo-booth queue system + staff dashboard

Public · two repos

Admins pre-register customers, generate one-time QR passes and drive a queue (waiting → session → review → complete) from a dashboard; customers scan and watch their live status.

Next.js 16React 19TypeScript Tailwind 4googleapisVercel
Engineering detail

The detail worth stating: the Google service-account key is base64-encoded into a server-side-only environment variable and never reaches the browser. A one-time QR pass is only "one-time" if the thing that mints it cannot be read by the person holding it.

13

Appointment booking — an authentication exercise

Public
Bank technical assignment

A compact full-stack application built deliberately around authentication and authorisation: admins see all appointments, users see only their own — enforced server-side.

FastAPISQLAlchemyPostgreSQL JWTReactpytestDocker
Engineering detail
  • Demo users seeded in code, idempotently, at startup — gated behind a flag that is forced off in production, where a single admin is bootstrapped from environment variables instead.
  • Passwords bcrypt-hashed, never stored or logged in the clear.
  • The pytest suite runs against a real PostgreSQL database, not SQLite — so the tests exercise the database production actually uses, including the constraint behaviour that differs between them.
14

VulnScan — port scanner & vulnerability assessment tool

Public · zero dependencies

A zero-dependency Python scanner that goes past open/closed: a 50+ port vulnerability database, five risk levels, banner grabbing to identify service versions, three to nine concrete remediation steps per finding, and JSON + text reports.

Python 3stdlib only100 threads
Engineering detail

Multi-threaded at 100 concurrent connections, shipping a written assessment report alongside real scan output. A finding without a remediation step is just an alarm; the value of the tool is in the three-to-nine things you can actually do about each one.

Paired with the ISC2 Certified in Cybersecurity credential. Intended and documented for authorised testing on networks you own — the repository carries a legal disclaimer.

15

FortuneClub — team full-stack project

67 commits · public
AIT coursework

A Django REST backend with a React + TypeScript frontend — chat, posts with image upload, and separate Docker images for development and production.

Django RESTReact · ViteTypeScriptDocker
Engineering detail

The number to lead with is 67 commits on a team project — the clearest evidence here of sustained, collaborative, iterative development, which is usually what a reviewer is actually looking for when they open a repository.

16

Earlier work — embedded, research and coursework

Foundation

The work the rest is built on: a senior project that went end to end from microcontroller to web dashboard, real embedded tooling, and a master's thesis.

What's in here
  • Full-stack IoT dashboard (senior project, KMUTNB) — end to end from C on an ESP32, through a LAMP stack on a Raspberry Pi, to a SQL-backed dashboard. The first system I owned from sensor to screen.
  • IoT design lab — ESP32 firmware in C++ built with PlatformIO, roughly 83 KB of C++: real embedded tooling rather than IDE sketches.
  • Master's thesis research (in progress) — electronic-nose development for fragrance and body-odour evaluation in the cosmetics industry, written in LaTeX with a reproducible toolchain.
  • Business-intelligence study hubs — around 50 hand-built, self-contained HTML pages published on GitHub Pages. Not software engineering, but evidence of technical writing, which matters more in solution and IT roles than people admit.

Projects marked client system are paid work under confidentiality. The architecture and engineering decisions here are mine to describe; client data, source code and internal documents are not published, and some systems are therefore described without a repository link. Happy to walk through any of them in detail.

Numbers I can stand behind

Each of these comes from an evaluation, a test suite or a source system — not an estimate.

8Production systems delivered to government, education and healthcare clients
98.9%Routing accuracy over a 92-question bilingual benchmark; 91.3–95.7% judge-verified answer correctness
10.85MPassenger records across five source systems, used for leakage-safe model training
3 → 85Tests grown over five weeks on the service desk; suite runtime 30s → under 1s
34-caseUAT driven through the real application with Playwright: 29 pass, 3 fail, 2 not exercisable
27-stepSmoke test walking an entire clinic business cycle, sale to case close
58/100 → shippedHCI usability score, followed by an actual remediation round
32-itemMaster-data audit where every "this stays in code" line must state a real reason
~21 reposPublic and private; 67 commits on the most active, 50 on the IoT platform