Backend and AI engineer · Tokyo

Lajat Manekar

I work on the backend of NEC HYDRAstor, a storage grid rated to 350 petabytes. I also work on NEC’s in-house generative AI platform. Outside work, I build infrastructure from first principles and measure it against the best in the field.

Now
Backend engineer, NEC HYDRAstor and NGS
Studying
MS Computer Science, Georgia Tech
Based in
Tokyo, Japanese at N3
Looking for
AI and backend roles in Tokyo

See my projects Résumé Get in touch

About

I grew up in Nagpur and studied computer science at Vishwakarma Institute of Technology in Pune, where I spent a lot of my time on competitive programming and open source. I started my career at ElasticRun, co-leading the work that made Central Authentication Service logins about 10x faster at peak and designing a multi-provider SMS routing service.

In 2023 MariaDB selected me as a Google Summer of Code contributor for its ColumnStore engine. The same year I took an offer from a company in Japan. I began learning Japanese from scratch so I could take it. I moved to Tokyo in February 2024 and have been working here ever since.

In January 2026 I began a Master’s in Computer Science at Georgia Tech, specializing in artificial intelligence. I’m drawn to the layer where systems meet machine learning: storage engines, retrieval and the infrastructure that makes AI dependable.

Day job

Inside a 350 PB storage grid.

Since February 2024 I’ve been a backend engineer in Tokyo on NEC HYDRAstor, the scale-out backup system enterprises trust with their data. I also work on NGS, NEC’s generative AI platform. The specifics are confidential, so this is what I can tell you.

  1. +20%system performance

    Backend engineering on NEC HYDRAstor

    HYDRAstor is a grid of storage nodes that backs up enterprise data. It deduplicates inline across the whole grid and erasure-codes data for resilience, so a change in the backend has to stay correct on systems customers rely on to recover. I work inside that backend, finding where it spends its time and rewriting the code that matters. That work raised system performance by about 20%.

  2. 90%test coverage

    Rebuilt the backend CI/CD testing pipeline

    When a storage system’s tests are slow or manual, every release is a risk. I rebuilt the entire backend CI/CD testing pipeline from scratch, on 10+ concurrent servers. It reached 90% test coverage, cut manual testing by 40% and made deployments 20% faster, so the team could ship with more confidence and less ceremony.

  3. 5,000+legacy lines refactored

    Shipped features into a production platform

    I’ve taken new product features from requirements through to release on a mature enterprise codebase. Much of that work is making old code safe to change first, so I refactored more than 5,000 lines of legacy code for maintainability along the way.

  4. −30%incident response time

    Keeping enterprise systems healthy

    Enterprise systems don’t get to be down. I work with support and engineering teams on production issues. We cut incident response time by 30% on systems running at 99.9% uptime.

  5. 20,000NGS users, reported by NEC

    Generative AI at NEC

    NGS, the NEC Generative AI Service, is the in-house LLM platform NEC built for its own employees, which NEC reports at 20,000 users. I work on it, which puts me at the point where backend reliability meets production AI.

  6. 20+knowledge-transfer sessions

    Raising the team around me

    Large systems live or die on shared understanding. I’ve led more than 20 knowledge-transfer sessions, working in a Japanese engineering environment after learning the language from scratch to join it.

HYDRAstor is rated to 350 PB of effective capacity and 5 PB/hr of backup throughput on NEC’s published HS8-50S specification.

What I’ve built

  1. EpzeroFaster than FAISS. Written from scratch.Vector database · C++201.08×hnswlib’s queries per second at recall 0.95, on SIFT1M
  2. AllfatherBug report in. Broken function out.AI code search · Learning to rank79.4%of 291 real bugs had a changed function in the top 10, out of 10k–45k candidates
  3. KhonsuUndo for AI agents.AI agent tooling · C++2324 / 24replays identical to the recorded run, with the model server switched off
  4. MaatKill the ledger. Lose nothing.Payment systems · Distributed backend¥0lost or double-charged across 13 verified load and failure runs

Look inside

Watch one of my systems work.

Pick a system, then watch a real request move through it, including what happens when things go wrong.

Swipe to see the whole diagram

OutsideRequest pathFast pathsThe moneyAfter the requestSimulatedWalletphone or tillEnvoy edgeidentityPayment serviceJavaLedgerKotlin, mTLS gRPCDynamoDBidempotency keysRedisQR codes, 5 minTiDBledger, paymentsOutbox relayrow → eventKafkaeventsSettlementdaily payoutsBank stubscripted failures

9 steps

A normal payment

You scan a shop’s code and press Pay. Here’s everything that happens in about 44 ms.

Step 1 of 9

The wallet picks a key first

Before the first attempt, the wallet chooses an idempotency key for this payment. It sends the request with your PIN approval, bound to that one key.

Step 2 of 9

The edge decides who you are

Envoy verifies your signed token, throws away any identity headers you claimed and sets its own. The service behind it trusts only that.

Step 3 of 9

Claim the key

A conditional write records this request. If the same key arrives again, the service finds this record and returns the original answer.

Step 4 of 9

Spend the QR code

Inserting the payment under a unique key on the QR code is what spends it. A second attempt on the same code fails on the key, so a cache can’t be wrong here.

Step 5 of 9

Reserve the money

The payment records AUTHORIZING, then asks the ledger to hold the amount. One conditional UPDATE does it. The row count is the verdict.

Step 6 of 9

Write balanced postings

On capture, ¥1,200 leaves the wallet, ¥1,164 is owed to the shop and ¥36 is fee revenue. Debits equal credits. The journal is append-only.

Step 7 of 9

State and event are one write

The result and a PaymentCaptured event are written in one transaction. The customer gets their answer now. Nothing has touched Kafka yet.

Step 8 of 9

Publish afterwards

A relay publishes the event later, carrying the original trace with it, so one payment is one trace from the edge to settlement.

Step 9 of 9

Settle at the end of the day

The settlement worker consumes the event. At payout, the ledger claims an exact set of postings. Three independent records must agree.

7 steps

The ledger’s answer is lost

This is the case the whole design is built around: the money may or may not have moved and nobody knows which.

Step 1 of 7

Write down the intent

The payment records CAPTURING before asking the ledger. This write-ahead state is what makes the next steps safe.

Step 2 of 7

Ask the ledger to capture

The request carries a key derived from the payment’s id, such as capture:{id}.

Step 3 of 7

The answer never arrives

The ledger did the work and committed it, but the response is lost on the network. The payment service sees a timeout.

Step 4 of 7

The API doesn’t guess

It answers 202 Accepted: “we don’t know yet”. Claiming success or failure here is how real systems lose money.

Step 5 of 7

Recovery re-drives the call

Every few seconds a recovery job finds work stuck in a write-ahead state and repeats the call with the same key.

Step 6 of 7

The ledger recognizes the repeat

A unique index finds the existing entry, so it returns what it already did instead of doing it again. The money moved exactly once.

Step 7 of 7

Finish normally

The payment completes. In the run where the ledger was killed twice, 4,005 payments ended like this. Every one resolved to exactly one outcome.

4 steps

A client retries

Your connection drops after you press Pay, so the wallet tries again. The customer must not be charged twice.

Step 1 of 4

The same request, again

The wallet resends with the same idempotency key. It doesn’t know the first attempt worked.

Step 2 of 4

Through the edge as usual

Nothing about the retry is special at this point.

Step 3 of 4

The key is already claimed

The conditional write fails, because this key has a stored answer.

Step 4 of 4

Same answer, no money moved

The original result is returned and the ledger is never called. I planted a bug that ignored these keys to prove the audit catches it: 200 of 200 wallets came out wrong.

5 steps

Kafka freezes

A dependency goes down. Each one has a decided failure mode. This one shouldn’t affect customers at all.

Step 1 of 5

Payments keep arriving

Nothing on the request path writes to Kafka, so customers can’t tell anything is wrong.

Step 2 of 5

Money still moves

The payment completes as normal. In the Kafka-frozen run, no request failed and p99 was 80 ms.

Step 3 of 5

Events wait in the outbox

Each event is safely in the database, in the same transaction as its payment. The alert watches how old the oldest unpublished event is.

Step 4 of 5

The relay can’t publish

Publishing fails and the rows stay put. Nothing is lost, because nothing has left the database.

Step 5 of 5

Kafka returns

The relay drains the backlog in order. Settlement catches up and the audit passes.

Component

Wallet

The client chooses an idempotency key when it shows “Pay ¥1,200”, before the first attempt. A double-tap or a retry sends the same key, so it can only ever be one payment.

Component

Envoy edge

The only way in. It verifies RS256 tokens and HMAC-signed shop requests, strips any identity a client claims and applies rate limits. No service publishes its own port.

Component

Payment service

Owns the life of every payment. It writes down what it’s about to ask the ledger before asking, so a crash or a lost answer leaves a record a recovery job can finish.

Component

Ledger

The only place a balance exists. It makes no outbound calls. Its database user can’t update or delete history. Every entry’s debits must equal its credits.

Component

DynamoDB

One record per client request, with the stored answer. Conditional writes make a retry recognizable. If this store is down, payments stop, because a retry could charge twice.

Component

Redis

Holds QR codes while they’re valid. It’s only a fast path: the code is really spent by a unique key in TiDB, not by deleting it here.

Component

TiDB

Everything that must be right. Each service has its own schema and database user. Unique keys and conditional updates here are what make the system correct.

Component

Outbox relay

Events are written in the same transaction as the change they describe, then published afterwards. There’s no moment when a payment is captured and its event doesn’t exist.

Component

Kafka

Everything downstream learns of changes here. A payment never waits for it. If Kafka freezes, payments keep succeeding and events queue in the outbox.

Component

Settlement

Pays merchants their net and reconciles three ways: events against ledger batches, payouts against entries and the bank statement against clearing accounts.

Component

Bank stub

A simulated bank with scripted latency, errors and timeouts, so failure paths can be tested on demand. All money in Maat is play money.

Read about Maat

Swipe to see the whole diagram

Your programKhonsuOutsideYour agentany frameworkToolsemail, refunds, filesLocal proxycanonical JSONrecording.khnCRC frames, hash chainMerkle snapshotsfiles before each callModel APIOpenAI, Anthropic, Ollama

7 steps

Record a run

You run your agent once through Khonsu. Nothing about your code changes.

Step 1 of 7

Snapshot the workspace

Before each call, the files are captured as a Merkle tree. Only new content is stored, so a later snapshot of a 20,000-file repository takes 34 ms.

Step 2 of 7

The agent calls the model

It thinks it’s talking to OpenAI. The proxy records the exact request.

Step 3 of 7

Forward to the real model

Requests pass straight through. Tokens stream back with no added latency.

Step 4 of 7

The answer comes back

Every chunk is forwarded immediately, except the very last one.

Step 5 of 7

Durable before observable

The final chunk is held until the frame is fdatasync’d. If the agent saw a response, it’s in the recording, even through kill -9.

Step 6 of 7

Now the agent can see it

Only then does the terminal event go out. API keys never reach the disk: the recording holds only <redacted>.

Step 7 of 7

Tools are recorded too

A real refund runs once and its result goes in the recording.

6 steps

Replay it

Same run, zero tokens, with the model server switched off.

Step 1 of 6

The agent runs again

It sends the same requests. It has no idea anything is different.

Step 2 of 6

Match by content

The proxy hashes the canonical request and finds the recorded response. Parallel calls can arrive in any order.

Step 3 of 6

Answer from the file

The response comes back with the original chunks and timing available.

Step 4 of 6

The model is never called

No tokens, no network, no cost. In my study, 24 of 24 replays were identical with the model server stopped.

Step 5 of 6

Side effects don’t repeat

The tool returns its recorded result, so the customer doesn’t get a second refund.

Step 6 of 6

Bit-exact

The run ends exactly as it did. The workspace is checked against each snapshot.

4 steps

Fork from a call

The agent went wrong at call 4. Go back and try a different future, paying only for what changes.

Step 1 of 4

Restore the world

The files are put back exactly as they were before call 4.

Step 2 of 4

Replay calls 0 to 3

Everything before the fork comes from the recording, with no tokens and no repeated side effects.

Step 3 of 4

Go live from call 4

From here the model is real again. After editing a prompt, 76% of tokens were served from the recording.

Step 4 of 4

A new recording, with a parent

The fork is saved linked to its parent. Forking the engine’s state costs one handle copy, 1.3 ns for 64 MiB.

3 steps

The run drifts

Someone edits a prompt and a test that replays a recording suddenly has a different request.

Step 1 of 3

A changed request

The agent sends something that isn’t in the recording.

Step 2 of 3

No match found

The content hash has no entry, so this is a divergence.

Step 3 of 3

Name the exact difference

Instead of a vague failure, Khonsu reports the first JSON field that changed, such as messages[0].content. In CI, the pytest fails with that message.

Component

Your agent

Runs unchanged. One environment variable points it at the local proxy, so it works with any language or framework.

Component

Tools

Functions marked with @khonsu.tool. Their results are recorded, so replay never sends the email or issues the refund twice.

Component

Local proxy

Sits at the HTTP boundary. It canonicalizes each request and matches on a hash plus an occurrence count, so parallel calls replay in any order.

Component

recording.khn

An append-only log. Each frame has a CRC32C. The end frame commits to a hash chain, so a flipped bit or a rewritten history is detected.

Component

Merkle snapshots

A content-addressed tree of the workspace before every call. Unchanged files are stored once and .env files are never captured.

Component

Model API

Only contacted when recording or going live. On replay it can be switched off completely.

Read about Khonsu

Swipe to see the whole diagram

Indexing the repositoryRanking a bug reportGitHubat the bug’s commitTree-sittersplits into functionsBM25 indexcode-aware wordsEmbeddingskeyed by contentBug reporttext, stack tracesRetrieve~40,000 → ~450LambdaMART52 featuresRerankertop 20, LoRA-tunedTop 10functions

7 steps

A real Django bug

django-11019: merging three media objects throws a false warning. The report never names the function that needs fixing. Watch where it ranks at each stage.

Step 1 of 7

Load Django at the right commit

The repository is read at the commit where the bug was filed, then split into every function and method.

Step 2 of 7

Plain keywords: not in the top 10

The report talks about MediaOrderConflictWarning. Simple word matching can’t find the merge code that causes it.

Step 3 of 7

Code-aware keywords: still missing

Splitting identifiers and excluding test files helps across the benchmark, taking 95 bugs to 159, but not on this one.

Step 4 of 7

Adding meaning: rank #10

Embeddings match what the report means, not just its words. A function the real fix changed enters the top 10 for the first time.

Step 5 of 7

Learned ranking: rank #3

LambdaMART combines dozens of weak signals. The fix climbs seven places.

Step 6 of 7

The reranker reads the code: rank #1

A fine-tuned model reads the issue and each function together and puts a function the real fix changed first.

Step 7 of 7

Checked against the real fix

Across 291 bugs, this cascade finds a right function in the top 10 for 79.4% and ranks one first for 45.0%.

6 steps

Search in your browser

allfather.dev does this for any public repository, on your own device. Only one optional step uses a server.

Step 1 of 6

One archive, streamed

A small Worker relays GitHub’s own archive, which the browser unpacks. Transformers loads in 5.0 s instead of 57 s.

Step 2 of 6

Parse on worker threads

Tree-sitter in WebAssembly runs on up to four threads. A partial index is published every 2.5 s, so large repositories are searchable while loading.

Step 3 of 6

Embed with a 16.8 MB model

A static model needs no neural network at encode time, so it handles thousands of functions a second per thread.

Step 4 of 6

Rank instantly

A LambdaMART model, shipped as JSON trees, ranks 33 features in milliseconds, with no server involved.

Step 5 of 6

An optional GPU reads the top 50

Only if it’s available, a reranker on Modal scores the top 50, adding 2.7 points on unseen projects. The browser’s order stays if it doesn’t answer.

Step 6 of 6

Same results as the Python engine

Parity tests require identical units, scores and ranker inputs, so the browser inherits the measured accuracy.

Component

GitHub

Each issue is searched at the commit where it was reported. Searching at HEAD would leak the fix.

Component

Tree-sitter

Parses every file into functions and classes, memoized by git blob id, so 188,880 files cost only 26,159 parses.

Component

BM25 index

Splits get_queryset into words and keeps the whole name, so prose and exact mentions both match. Weights live in a sparse matrix.

Component

Embeddings

A code embedding model, cached by content hash. 6.67 million slots became 185,000 distinct texts, about 15 minutes of GPU instead of 9 hours.

Component

Bug report

Stack frames, backticked names, paths and error strings become separate signals, not just more words.

Component

Retrieve

BM25 and dense search fail differently, so fusing them beats either alone. The pool keeps a right answer for 96.7% of issues.

Component

LambdaMART

Gradient-boosted trees weigh retrieval scores, tracebacks, mentions, git history and past fixes. History only uses commits before the bug.

Component

Reranker

A cross-encoder reads the issue and code together. Off the shelf it added nothing. Fine-tuned on hard negatives, it lifted MRR by 0.063.

Component

Top 10

Scored against the functions the maintainers’ real fix changed and never tuned on the test set.

Read about Allfather

Swipe to see the whole diagram

ClusterInside one engineClientHTTP or gRPCGo routershards, failoverPrimaryC++ nodeReplicaC++ nodeWrite-ahead logCRC32C framesUpper layerssparse express lanesBase layerall vectors, beam efSIMD kernelsAVX-512, NEON, WASMRecall guardlive recall

7 steps

A search

One query, answered in about 175 µs at 97% recall, on a million vectors.

Step 1 of 7

A query arrives

The router fans it out to one live copy of every shard. If one copy is slow, it hedges to the other.

Step 2 of 7

Into the index

Reads take no locks, so a search never waits behind an insert.

Step 3 of 7

Take the express lanes

Starting from one entry point, the search hops greedily through sparse layers. A few long hops cover most of the distance.

Step 4 of 7

Drop to the dense layer

A beam of the ef best candidates expands the closest unexplored node until nothing left can beat the beam.

Step 5 of 7

Overlap the cache misses

Instead of scoring neighbors one at a time, it prefetches them all first. Search is bound by DRAM latency, so overlapping up to 32 misses is the biggest win.

Step 6 of 7

Score with SIMD

Hand-written kernels compute distances. About 1,500 of a million vectors are touched, roughly 243× fewer than an exact scan.

Step 7 of 7

Merge and return

The router merges each shard’s top-k and returns the answer.

6 steps

A write

A vector must survive a crash the moment it’s acknowledged.

Step 1 of 6

The router picks a shard

The label is hashed to a shard. The write goes to that shard’s primary with its current epoch.

Step 2 of 6

Epoch check

A node refuses writes from an older epoch, which fences off a router or primary that doesn’t know it’s been replaced.

Step 3 of 6

Log it first

The record is appended to the write-ahead log with a CRC32C, using group commit.

Step 4 of 6

Forward to the replica

If the replica is in sync, the primary forwards the write and waits for it.

Step 5 of 6

Insert into the graph

Neighbor slots are published with release stores, so a concurrent reader that sees a node also sees its vector.

Step 6 of 6

Tell the truth about durability

The response says whether both copies have it. Writes stay available with one copy down. The client is told so.

5 steps

The primary dies

A node crashes under traffic. CI kills a primary on every push and checks that nothing is lost.

Step 1 of 5

Health checks start failing

After three missed checks, the router declares the node down.

Step 2 of 5

Promote the replica

The router raises the shard’s epoch and makes the replica primary. The old epoch is now fenced.

Step 3 of 5

Traffic continues

Strong reads resume on the new primary. Searches keep answering from the live copies.

Step 4 of 5

The old primary returns

It can’t just resume: it may hold writes that were never replicated. It rejoins as a replica from a snapshot.

Step 5 of 5

Proven, not assumed

A simulation checks histories with Porcupine under crashes and partitions. It found a retried write applied twice and a replica serving stale reads. Both are fixed.

4 steps

Recall drifts

Accuracy quietly drops in production. Almost nobody measures this. Epzero does.

Step 1 of 4

Real traffic flows

Deletes, filters and new query patterns change recall. No error is raised.

Step 2 of 4

Sample without slowing search

A lock-free counter copies every n-th query to a bounded queue. When the queue is full, samples are dropped rather than waited for.

Step 3 of 4

Answer it a better way

The guard re-answers the sample exactly, then compares results to estimate recall with a confidence interval.

Step 4 of 4

Move the beam

It widens the beam as soon as measured recall falls short and narrows it only on confident surplus. On SIFT1M it held 0.95 at 6–15% less cost than over-provisioning.

Component

Client

Applications send vectors to search or store. Each search can choose strong or eventual consistency.

Component

Go router

Owns the shard map, health-checks nodes, hashes writes to a primary, fans searches out with hedging and merges top-k results.

Component

Primary

Takes all writes for a shard. A write goes to its log, then its in-sync replica, before it’s acknowledged. An epoch fences any stale writer.

Component

Replica

A second copy on another node. It answers reads only while both copies report it’s in sync and is promoted if the primary dies.

Component

Write-ahead log

Group-committed, checksummed records and atomic checkpoints. Recovery keeps the longest valid prefix, tested with a torn write at every byte offset.

Component

Upper layers

Sparse graph layers with long links. A search descends greedily from one entry point, covering most of the distance in a few hops.

Component

Base layer

The dense bottom layer, on 2 MiB huge pages with each vector beside its neighbor list. A beam of ef candidates finds the answer here.

Component

SIMD kernels

Hand-written distance kernels, picked at runtime. With 8-bit codes, one VNNI instruction handles up to 64 dimensions.

Component

Recall guard

Re-answers a sample of real queries on its own thread and reports recall with a Wilson interval. It widens the beam on a measured shortfall.

Read about Epzero

How I work

  1. If it isn’t measured, it didn’t happen

    Every Allfather improvement ships with a paired significance test. Every Epzero optimization had to win an interleaved A/B test or be deleted.

  2. Kill your darlings in public

    Graph reordering, LTO and call-graph expansion all sounded right. The numbers disagreed, so they’re gone and the write-ups say why.

  3. Break it before production does

    I plant bugs to test the tests. I kill -9 mid-write. I check reads for linearizability under partitions. A guarantee that has never been attacked is only a hope.

Experience

  1. Feb 2024 – Present

    Backend Engineer

    Human Resocia, assigned to NEC · HYDRAstor and NGS · Tokyo, Japan

    HYDRAstor backend

    • Engineer the backend of NEC HYDRAstor, a storage grid rated to 350 PB and 5 PB/hr.
    • Raised system performance 20% with better algorithms and high-performance modules.
    • Resolved 100+ bugs and shipped module updates as patches on an enterprise codebase.

    Testing and reliability

    • Rebuilt the backend CI/CD testing pipeline from scratch on 10+ concurrent servers.
    • Reached 90% test coverage, cut manual testing 40% and sped up deployments 20%.
    • Cut incident response time 30% with support teams, on systems at 99.9% uptime.

    Generative AI

    • Work on NGS, NEC’s in-house LLM platform, which NEC reports at 20,000 users.

    Recognition

    • Received the NEC Value Engineering (VE) President’s Award.
  2. 2023

    Relocation to Japan

    Offer from a Tokyo employer · Pune, India

    • Learned Japanese from scratch to NAT-TEST N3 and moved to Tokyo in February 2024.
    • Selected as one of MariaDB’s six Google Summer of Code contributors for ColumnStore.
  3. Jan 2022 – Jan 2023

    Intern, then Associate Software Engineer

    ElasticRun · Pune, India

    Performance and data

    • Co-led Central Authentication Service optimization for about 10x faster peak logins.
    • Co-led performance optimization of a high-volume shipment app’s APIs and database.
    • Built a MySQL compatibility layer for a MariaDB framework, readying TiDB migration.

    Platforms

    • Designed multi-provider SMS routing that held about 99% availability during outages.
    • Built a cloud automation and change management platform across Kubernetes clusters.
    • Owned the core application framework, turning requirements into reusable capabilities.
  4. Expected Fall 2027

    MS in Computer Science, Artificial Intelligence

    Georgia Institute of Technology

  5. 2018 – 2022

    B.Tech in Computer Science

    Vishwakarma Institute of Technology, Pune

Skills

Systems and performance

C++20/23, SIMD: AVX2, AVX-512, NEON, Lock-free concurrency, WebAssembly, Sanitizers, libFuzzer

Backend and distributed systems

Java, Kotlin, Go, Python, gRPC, Kafka, Redis, TiDB, DynamoDB, Envoy

AI and retrieval

PyTorch, LambdaMART, LoRA fine-tuning, Embeddings, Hybrid search, HNSW, ONNX Runtime, Offline evaluation

Infrastructure and operations

CI/CD, Kubernetes, Helm, Terraform, AWS, Cloudflare Workers, Prometheus, Grafana, OpenTelemetry, Ansible, Jenkins

Open source and earlier work

Let’s talk.

Open to AI and backend engineering roles in Tokyo.