Senior Backend Engineer·99.co Singaporenow
Sep 2025 – PresentJakarta, Indonesia · PropTech for SG & ID
I build backend systems, internal tools, and performance-conscious products. Currently Senior Backend Engineer at 99.co, shipping PropTech systems for 20M+ users. Previously at Kredivo (core banking, payments) and Jublia (AI event matchmaking).
I work mostly in Go and Python, care about clean architecture, observability, and pragmatic security, and I write about engineering at lori.my.id. Open to senior backend and systems-oriented roles.
I like systems with hard edges: payment flows that must stay atomic, APIs that should degrade predictably under failure, and internal tools that remove operational drag instead of adding more abstraction. Most of my work lives in Go and Python, usually around backend services, data flow, observability, and developer-facing tooling.
I started on Linux and security, still think with that bias, and tend to optimize for pragmatic architecture over novelty. Outside paid work I build tools to scratch my own itches and write about performance, debugging, and systems thinking at lori.my.id.
Jakarta, Indonesia · PropTech for SG & ID
Remote
Jakarta, Indonesia · SE Asia FinTech (digital credit, lending, banking)
Remote · AI-powered global event-matchmaking platform
Surakarta, Indonesia
Production-ready Go service template I actually reuse. Clean Architecture with REST + gRPC, Redis caching, pessimistic locking, circuit breakers, testcontainers, and CI, so a new service starts from operational defaults instead of tutorial scaffolding.
Single-file bash monitor for nginx + host on small VPSes. Discord, Slack,
Telegram, and Matrix alerts with cooldown and cross-rule dedup, σ-based
anomaly detection over a 14-day baseline, host-integrity audits, and an
optional eBPF probe sidecar streaming kernel events through the same alert
pipeline. Modular src/*.sh bundled to one milog.sh
so operators install one file.
Container kernel auditor for shared-kernel escape risk on Linux. Static
posture checks (cgroups, namespaces, capabilities, seccomp, LSM) plus a
small eBPF probe on syscall tracepoints, correlated in a Rust userspace
engine that flags chains like AF_ALG + splice() followed by
a root UID transition. Surfaces Copy Fail (CVE-2026-31431) exposure
without running exploit code.
Native API client in Rust + egui built to replace Postman in my own workflow. Uses roughly 10 MB RAM instead of Postman's 500 MB+, skips Electron entirely, stores everything locally, and starts fast enough to feel like a real desktop tool.
Dependency-free Rust URL shortener: one native binary, one
links.tsv file, in-memory hash lookup, direct
302 redirects. No database process, no framework
runtime. The deliberate opposite of "stand up Postgres + an
ORM + a worker queue to redirect twelve URLs."
Invite-only Go web app for mentors and teachers to track progress without spreadsheets or a heavy LMS. Supports both long-running 1:1 mentorship rooms and cohort-style classrooms in the same instance — progress reports, link-based submissions, 1–5 rubric scoring, comments. Built after mentoring vocational-school teachers and watching them lose track in WhatsApp threads.
Calm, private reader for personal libraries. Upload PDFs, EPUBs, and Markdown, read across devices with themes, font controls, highlights, and progress that follows you. One-click PDF→EPUB conversion via headless Calibre, optional Cloudflare R2 storage, single-binary Go server.
Free, private personal finance tracker with running balance, smart category prediction, anomaly alerts, and 10 planning tools (“can I afford this?”, “when can I retire?”). Built for people who hate spreadsheets and subscriptions.
Goal: start new services with production defaults already in place instead of rebuilding the same infrastructure decisions from scratch.
Tradeoff: a little more setup up front, but the payoff is consistent service boundaries, testable modules, and fewer ad hoc decisions under delivery pressure.
Goal: cover the operational basics on a single small VPS — nginx alerts, host integrity audits, kernel observability — without a SaaS bill or a fleet of agents to babysit.
Tradeoff: bash for what bash does well and cilium/ebpf-go for what bash genuinely cannot reach means two dialects to maintain, but the shipping artifact stays one POSIX script plus an optional Go binary. That is what operators with one to three boxes actually want, instead of a uniform Go agent that needs its own packaging story.
Goal: give engineers a defensive lens on shared-kernel container risk — answer "is this host safe to run untrusted workloads on?" with both static posture and live syscall correlation, not just a CVE feed lookup.
Tradeoff: a tiny C/eBPF probe runs in the kernel verifier sandbox while the heavier auditor stays in Rust. Splitting languages means two build paths to maintain, but it keeps the kernel surface minimal and verifier-safe while the userspace tool gets memory safety, structured parsing, sequence correlation, and clean JSON/JSONL output. Correlating chains (AF_ALG + splice, namespace + mount, exec + UID transition) instead of single syscalls is what makes findings actionable instead of noisy.
Goal: make an API client that feels native and disposable, so opening it for a quick request does not cost hundreds of megabytes or a full browser-stack boot.
Tradeoff: less plugin ecosystem than Postman, but much better startup feel, lower memory use, and tighter local-only ownership of request data.
Goal: show that "URL shortener" doesn't need a Postgres + ORM + worker queue + Kubernetes deployment — a TSV file and an in-memory hashmap covers the actual workload for personal and small-team use, with effectively zero ongoing maintenance.
Tradeoff: editing a TSV instead of hitting a write API means restart-to-update and no high-write throughput, but the binary fits in a tiny VM, has almost no attack surface beyond the redirect logic, and stays trivially portable across boxes.
Goal: give mentors and teachers a shared room for tracking real progress without forcing them into a spreadsheet (loses structure under load) or a full LMS (too heavy, too institutional for a small mentor program).
Tradeoff: holding mentorship and classroom shapes inside one app means a slightly heavier domain model than either alone, but it matches how mentors actually work — a single instance can run a long-running 1:1 cohort and a short, scored class side by side without standing up two systems. Server-rendered templates over SQLite keep the deploy story to one binary.
Goal: give people a calm, private place to read their own libraries without the storage assumptions and tracking of Kindle, Google Books, or ad-funded readers.
Tradeoff: shipping a single Go binary plus an embedded reader (epub.js + pdf.js) means leaning on browser-grade rendering instead of a native engine, but it keeps the deploy story simple, the data local-first by default, and the upgrade path painless — SQLite for state, optional R2 only when you want cross-device sync.
Goal: a personal finance tool that does the thinking — running balance, anomaly alerts, "can I afford this?" — without becoming yet another subscription you forget to cancel.
Tradeoff: a server-backed app on PostgreSQL is more infrastructure than a spreadsheet, but the payoff is real category prediction, drift detection over time, and OAuth so it works across devices instead of living on one laptop.
signed -10 is greater than unsigned 5 in C
An implicit type conversion that bites every C beginner once. Tracing exactly how the comparison flips and what to do about it.
→
Lori
Software Engineer · Open to opportunities