# Ivan Karpinskyi — Full-stack engineer, backend first

> I build backends and take them all the way to production. Node.js, NestJS, PostgreSQL. Case studies of systems I run, and notes on how backends behave.

- Source: https://ivankarpinskyi.dev/

**I build backends and take them all the way to production.**

Full-stack engineer, backend first. 4+ years with Node.js, NestJS and PostgreSQL. Below: systems I designed, shipped and still run, from a law firm's platform on its own AWS to an AI video pipeline on queues, and notes on how backends behave.

- Backend: Node.js, NestJS, REST and queues
- Data: PostgreSQL, pgvector, Redis
- Queues: BullMQ workers, retries, idempotency
- Runs on: AWS, Docker, Terraform, my own servers

## Built, shipped and run by one engineer.

- [Connect](https://ivankarpinskyi.dev/work/connect.md): Platform and release pipeline for a law firm. Docker · Terraform · one-command release with rollback
- [ClipNest](https://ivankarpinskyi.dev/work/clipnest.md): An AI video pipeline on queues. NestJS · BullMQ · pgvector · FFmpeg on Lambda
- [Dimori Park Group](https://ivankarpinskyi.dev/work/dimori-park-group.md): Off the CMS server: one app for every location. Strapi + GraphQL on EC2 → Keystatic, nothing to run
- [A11ySignal](https://ivankarpinskyi.dev/work/a11ysignal.md): Accessibility scans as a pipeline. BullMQ jobs · Chromium pool · scan diffs

## Notes on how backends behave

Every note starts as a question from real work, researched until the answer holds up. Sources at the end of each.

- [Dual writes will bite you: choosing between a polling outbox and CDC](https://ivankarpinskyi.dev/blog/outbox-vs-dual-writes.md) (2026-10-06, Decision): A dual write has no safe ordering. How polling outboxes skip rows and bloat, how CDC slots fill disks, and how to pick the relay your team can run.
- [The negative leap second: the clock bug nobody has rehearsed in production](https://ivankarpinskyi.dev/blog/negative-leap-second.md) (2026-10-08, Changes): All 27 leap seconds added time and still broke Linux and Cloudflare. A deleted second jumps clocks forward instead, and on 15 October 2026 the CGPM votes.
- [Timestamps lie: why ORDER BY created_at isn't ordering](https://ivankarpinskyi.dev/blog/clocks-lie-distributed-systems.md) (2026-09-28, Mechanism): Wall clocks drift, step and freeze, so created_at cannot order writes. How last-write-wins loses data, and what logical clocks and fencing tokens fix.
- [Your query's latency lives where you deployed it](https://ivankarpinskyi.dev/blog/query-path-await-to-response.md) (2026-09-20, Mechanism): The path from await query() to a row has five measurable stages. Which one owns your latency is decided by deployment shape, not by the query.

## Where I've worked

- **MB-Digital** (Mar 2026 – Aug 2026): Software Engineer · AdTech and marketing automation
- **Clover Dynamics** (Aug 2023 – Feb 2026): Software Engineer · Web applications
- **Appexoft** (Jan 2023 – Jul 2023): Software Engineer · Backend services and integrations

I'm Ivan, an engineer from Ukraine. I started on the backend and still think from the database up. If you want to talk about a role, a system or a note, write to me.

- Email: mailto:ivankarpinskij.ua@gmail.com
- LinkedIn: https://www.linkedin.com/in/ivan-karpinskyi/
- GitHub: https://github.com/KarpAAA
