WE NEED 47 MICROSERVICES TO PARSE A JSON (AND OTHER ENTERPRISE LIES)

**por. Zbigniew 2 luty 2026 Poziom cynizmu: BEYOND ENTERPRISE**

A data-driven takedown of enterprise software complexity


THE PROBLEM

We need to extract a person’s name, email, and phone from a CV.

The CV is in JSON format (JSON Resume), a standard with 50 fields that has been stable since 2014.

Here’s the input:

{
  "basics": {
    "name": "Jan Kowalski",
    "email": "jan@example.com",
    "phone": "+48 123 456 789"
  }
}

Here’s what we need:

{
  "first_name": "Jan",
  "last_name": "Kowalski",
  "email": "jan@example.com",
  "phone": "+48 123 456 789"
}

How hard can this be?


THE ENTERPRISE SOLUTION

Architecture Diagram

+---------------------------------------------------------+
|  API Gateway (Kong)                                      |
+----------------------------+----------------------------+
                             |
+----------------------------v----------------------------+
|  cv-ingestion-service                                    |
+----------------------------+----------------------------+
                             | Kafka
+----------------------------v----------------------------+
|  cv-validation-service                                   |
+----------------------------+----------------------------+
                             | gRPC
+----------------------------v----------------------------+
|  basics-parser-service                                   |
|  work-parser-service                                     |
|  education-parser-service                                |
|  skills-parser-service                                   |
+----------------------------+----------------------------+
                             | Redis pub/sub
+----------------------------v----------------------------+
|  aggregation-service                                     |
+----------------------------+----------------------------+
                             | RabbitMQ
+----------------------------v----------------------------+
|  form-mapping-service                                    |
+----------------------------+----------------------------+
                             | MongoDB
+----------------------------v----------------------------+
|  caching-service (Redis cluster)                         |
|  monitoring-service (Prometheus + Grafana)               |
|  tracing-service (Jaeger)                                |
|  logging-service (ELK stack)                             |
+---------------------------------------------------------+

15 services. For one JSON.

The Java Code

@Component
@Primary
@Qualifier("abstractCVProcessorFactoryBeanManagerImpl")
public class AbstractCVProcessorFactoryBeanManagerImpl
        implements CVProcessorFactoryBeanManager,
                   CVProcessorFactoryBeanManagerLifecycle,
                   CVProcessorFactoryBeanManagerAware {

    @Autowired
    @Qualifier("cvProcessorStrategyProviderFactoryBean")
    private CVProcessorStrategyProviderFactoryBean
        cvProcessorStrategyProviderFactoryBean;

    // ... 200 more lines ...
}

This is one of 52 Java classes required to parse a name out of JSON.

The Numbers

Metric Value
Lines of code 4,200+
Java classes 52
XML config files 23
Maven dependencies 23
Kubernetes YAMLs 47
Startup time 12.3 seconds
Memory at rest 256 MB
Time to debug “name is null” 2-4 hours

THE ABSURDIST COLLECTION

CGI-Perl (1997)

#!/usr/bin/perl
use CGI qw(:standard);
$json = param('cv');
$json =~ /"name"\s*:\s*"([^"]+)"/;
$name = $1;
# No strict, no warnings, no JSON module
# Parse with regex, what could go wrong?

CGI-C (Buffer Overflow Edition)

char buffer[256];  // What's the worst that could happen?
fread(buffer, 1, content_length, stdin);  // No bounds checking
char* name = strstr(buffer, "\"name\"");
// Parse JSON by hand with strchr and strstr

This code has 5 exploitable vulnerabilities. It also works 99% of the time.

Node.js Callback Hell (Pre-2015)

parseCV(cv, function(err, parsed) {
  if (err) return callback(err);
  validateBasics(parsed, function(err, valid) {
    if (err) return callback(err);
    extractName(valid, function(err, name) {
      if (err) return callback(err);
      splitName(name, function(err, parts) {
        if (err) return callback(err);
        // ... 15 more levels ...
      });
    });
  });
});

250 lines of nested callbacks. Zero Promises. Zero async/await.


THE BENCHMARK RESULTS

We benchmarked every solution. Real numbers. Real hardware.

Solution LOC Files Dependencies Startup Memory Throughput p99 Latency
Python (lean) 93 1 0 0ms 12MB 530,665/s 0.00ms
CGI-C 89 1 0 5ms 2MB 50,000/s SEGFAULT
Node.js Callback Hell 250 1 0 150ms 80MB 5,000/s 8.00ms
CGI-Perl 45 1 1 50ms 15MB 2,000/s 10.00ms
Java Enterprise 4,200 52 23 12s 256MB 850/s 45.00ms
AWS Serverless 2,100 34 12 800ms 128MB 500/s 800.00ms
K8s Microservices 8,400 89 156 3 min 2,400MB 150/s 1,200.00ms

The Python script is 3,500x faster than the Kubernetes microservices solution.

It uses 200x less memory.

It has 93 lines vs 8,400 lines.


THE REAL SOLUTION

from dataclasses import dataclass
from typing import Optional

@dataclass
class FormData:
    first_name: str
    last_name: str
    email: str
    phone: Optional[str] = None

def parse_cv(cv: dict) -> FormData:
    basics = cv.get("basics", {})
    name_parts = basics.get("name", "").split(" ", 1)

    return FormData(
        first_name=name_parts[0] if name_parts else "",
        last_name=name_parts[1] if len(name_parts) > 1 else "",
        email=basics.get("email", ""),
        phone=basics.get("phone"),
    )

That’s it. That’s the whole thing.

  • Zero dependencies
  • 93 lines including tests
  • 530,665 CVs/second
  • Works in any Python 3.10+ environment
  • 100% test coverage

Or if you prefer the shell:

jq '.basics | {
  first_name: .name | split(" ")[0],
  last_name: .name | split(" ")[1:] | join(" "),
  email,
  phone
}' cv.json

One line. That’s the entire ATS industry’s core technology.


THE COST ANALYSIS

Processing 1 million CVs per month:

Solution Infrastructure Dev Time Monthly Cost
Python script $5 VPS 2 hours $5
AWS Lambda Serverless 1 week $50
K8s Microservices EKS cluster 3 months $2,400
Enterprise Java On-prem servers 6 months $15,000

The $2.5 billion ATS market is charging enterprise prices for a shell script.


WHY DO COMPANIES DO THIS?

1. Conway’s Law

“Organizations design systems that mirror their communication structure.”

If you have 15 teams, you get 15 microservices.

2. Resume-Driven Development

Engineers want Kubernetes on their resume. Nobody wants “wrote a shell script.”

3. The Complexity Tax

Complexity creates job security. Simple solutions make roles redundant.

4. Vendor Lock-in

Enterprise software vendors sell complexity. Simple solutions don’t require consultants.

5. Cargo Culting

“Netflix uses microservices, so we should too.”

Netflix has 200 million users. You have a JSON file.


THE WORKDAY SPECIAL

Workday, the $64 billion HR software company, processes CVs using:

  • Xpresso: A proprietary GUI-based “programming language”
  • 47-step wizards to map a single field
  • 3-day training required to use basic features
  • Documentation behind paywall

Their core technology? The same string splitting you saw in the Python script.


THE DESKTOP APP DISASTER (ELECTRON EDITION)

“We need a native app for better UX.”

So someone decided to build a CV parser as an Electron app. Here’s what that means:

The package.json

{
  "dependencies": {
    "electron": "^28.0.0",
    "react": "^18.2.0",
    "redux": "^5.0.0",
    "redux-saga": "^1.2.0",
    "mobx": "^6.10.0",
    "zustand": "^4.4.0",
    "axios": "^1.6.0",
    "got": "^13.0.0",
    "node-fetch": "^3.3.0",
    "moment": "^2.29.4",
    "date-fns": "^2.30.0",
    "left-pad": "^1.3.0",
    "is-odd": "^3.0.1",
    "is-even": "^1.0.0"
  }
}

287 dependencies to parse a JSON file.

Including:

  • 5 state management libraries (Redux, MobX, Zustand, Recoil, Jotai) - couldn’t decide
  • 9 HTTP client libraries - in case axios breaks
  • 4 date libraries - time is hard
  • 47 is-* packages - is-odd, is-even, is-number, is-null…
  • left-pad - obviously

The Build Pipeline

TypeScript -> Babel -> Webpack -> Rollup -> esbuild -> Parcel -> Vite -> Electron Builder

7 bundlers. For 4 lines of business logic.

The Numbers

Metric Electron App jq one-liner
Dependencies 287 1
node_modules size 2.1 GB 0
Build time 12 minutes 0
Final size 387 MB 1.2 MB
RAM at idle 1.2 GB 4 MB
Startup time 8.3 seconds 2 ms
Vulnerabilities 127 (14 critical) 0

The Vulnerability Report

127 vulnerabilities found

  14 critical severity
  38 high severity
  47 moderate severity
  28 low severity

Run `npm audit fix` to fix 23 of them.
104 require manual review.

MS Teams uses this architecture. For a chat app. That uses 1.2 GB of RAM. To send messages.

IRC clients in 1998 used 2 MB.


WHAT SHOULD YOU ACTUALLY USE?

For a Browser Extension

export function parseCV(cv: JSONResume): FormData {
  const basics = cv.basics ?? {};
  const [firstName = '', ...rest] = (basics.name ?? '').split(' ');
  return { firstName, lastName: rest.join(' '), email: basics.email ?? '' };
}

For a Backend Service

def parse_cv(cv: dict) -> FormData:
    basics = cv.get("basics", {})
    name_parts = basics.get("name", "").split(" ", 1)
    return FormData(first_name=name_parts[0], last_name=name_parts[1] or "")

For Bulk Processing

find ./cvs -name "*.json" | parallel jq '.basics | {name, email}' {}

For an API

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

@app.post("/parse")
def parse(cv: dict) -> FormData:
    return parse_cv(cv)

Done. Deploy to a $5/month VPS. Handle millions of requests.


THE UNCOMFORTABLE TRUTH

The $2.5 billion ATS market is built on 50 lines of code.

Every “enterprise-grade solution” is just:

  1. json.loads()
  2. name.split(" ")
  3. .get("email")

Everything else is overhead.

Not useful overhead. Not necessary overhead. Just… overhead.


TRY IT YOURSELF

# Install the lean Python package
pip install cv-autofill

# Or use jq
echo '{"basics":{"name":"Jan Kowalski","email":"jan@x.com"}}' | \
  jq '.basics | {first: .name | split(" ")[0], last: .name | split(" ")[1], email}'

GitHub: cv-processor-benchmark

All code is MIT licensed. Use it. Mock the enterprise solutions. Build something simple.


“Simplicity is the ultimate sophistication.” - Leonardo da Vinci

“We need 47 microservices.” - Every Enterprise Architect


Disclaimer: This article was written without Kubernetes, without microservices, and without consulting a single enterprise architect. It still works.