Wednesday, February 4, 2026

Salary Hardening in India

 Software engineering salaries hardened in India around 2000-2004, were the causes for that? Did some promising engineers have to sacrifice their careers via attrition for the others to reap dividends?

Short answer: yes, salaries hardened (flattened/plateaued) in 2000–2004, and yes, a non-trivial number of capable engineers did fall out of the system, which indirectly made the later boom possible—but it wasn’t a clean or fair process.

Let’s unpack it calmly, without nostalgia or propaganda.


What actually happened (2000–2004)

1. Dot-com bust hit India with a lag

  • 1998–2000: irrational exuberance, campus offers flew, startups everywhere

  • 2000–2001: US tech crash → contracts cancelled → Indian IT feels it in 2001–2002

  • Hiring freezes, offer revocations, bench strength exploded

India didn’t crash spectacularly—but it froze.


2. Wage hardening = demand shock + supply overhang

  • Suddenly too many engineers for too few billable projects

  • Companies responded by:

    • Freezing increments

    • Normalizing very low starting salaries

    • Introducing long “training/bench” periods

  • This reset the salary baseline for almost a decade

Many people mistake this for “discipline.” It was really risk transfer to labor.


3. Attrition wasn’t just weak engineers

This is the uncomfortable part.

A lot of people who exited were:

  • First-gen engineers with no financial buffer

  • Talented but:

    • From non-tier-1 colleges

    • Poor at corporate politics

    • Unwilling to wait 18–24 months on bench

  • People who couldn’t afford unpaid “learning time”

They didn’t fail technically.
They failed economically.

Some went into:

  • Banking clerical jobs

  • Teaching

  • Family businesses

  • Completely unrelated fields

And yes—some of them would’ve been excellent engineers had timing been different.


Did their sacrifice benefit the survivors?

Indirectly, yes—but not in a heroic way.

How the system benefited:

  • Reduced bargaining power of employees

  • Created a large, compliant middle layer

  • Made offshore delivery predictable and cheap

  • Allowed Indian IT to scale massively post-2004

The survivors didn’t “win” because they were best.
They won because they lasted.

This is important:

The Indian IT miracle was built more on endurance and cost control than on meritocracy.


Why salaries didn’t rebound quickly (even after recovery)

Three structural reasons:

1. Services model ≠ innovation rents

  • Billing tied to hours, not outcomes

  • No IP upside → no salary elasticity

2. Freshers as commodities

  • Companies optimized for replaceability

  • Skill depth intentionally postponed

3. Fear memory

Leadership that lived through 2001–02:

  • Became conservative

  • Over-indexed on cost discipline

  • Institutionalized low pay as “prudence”

That trauma lasted long.


A subtle but lasting cultural effect

This period taught Indian engineers:

  • Don’t rock the boat

  • Stay billable

  • Avoid specialization early

  • Loyalty > curiosity (at least visibly)

You can still see that DNA today.


Bottom line (no romance)

  • Yes, salaries hardened due to a global shock + structural choices

  • Yes, good engineers were lost, not because they were weak, but because the system couldn’t carry everyone

  • The later boom rode on:

    • Cheap, stable labor

    • Process maturity

    • Global demand—not justice

History didn’t select the best.
It selected the survivable.

If you want, we can also:

  • Compare this with post-2022 layoffs

  • Map who gets filtered out today

  • Or talk about how to design systems that don’t waste talent this way

Tuesday, February 3, 2026

Full Stack Development - Class 6 - Javascript Strings

 In JavaScript, a string is a primitive data type used to represent and manipulate a sequence of characters, such as text. Strings are immutable, meaning their content cannot be changed after they are created; any operation that seems to modify a string actually creates a new one.

Creating Strings
Strings can be created using three types of quotes:

Sunday, February 1, 2026

Full Stack Development- Class 5 - Arrays

 JavaScript arrays are ordered, zero-indexed collections of values stored under a single variable name. They are a fundamental data structure, enabling efficient storage and manipulation of lists of data. Arrays in JavaScript are dynamic, meaning they can resize and hold a mix of different data types. 

Key Characteristics
  • Ordered and Zero-Indexed: Elements are stored in a specific order and accessed using a numeric index, starting at 0 for the first element.
  • Dynamic Size: Arrays can grow or shrink as elements are added or removed, without needing to define a fixed size upfront.
  • Heterogeneous: A single array can contain different data types, such as strings, numbers, objects, and even other arrays.
  • Objects: Arrays are special types of objects in JavaScript; the typeof operator returns "object" for arrays.
  • Shallow Copies: Built-in array-copy operations create shallow copies, meaning nested objects within the array still refer to the same object in memory. 
Creating Arrays
The most common and preferred way to create an array is using array literals (square brackets). 
// Creating an empty array
let emptyArray = [];
// Creating an array with initial values
const fruits = ["Banana", "Orange", "Apple", "Mango"];
// Output: ["Banana", "Orange", "Apple", "Mango"]
Common Operations and Methods
JavaScript provides numerous built-in methods for array manipulation. Some of the most frequently used methods are: 
Accessing Elements: Use the index in square brackets to access a specific element:
let firstFruit = fruits[0]; // "Banana"
let lastFruit = fruits[fruits.length - 1]; // "Mango"
  • Adding Elements:
    • push(): Adds one or more elements to the end of an array.
    • unshift(): Adds one or more elements to the beginning of an array.
  • Removing Elements:
    • pop(): Removes the last element from an array.
    • shift(): Removes the first element from an array.
    • splice(): A versatile method for adding/removing elements at any specific position.
  • Iterating: Use methods like forEach()map(), or filter(), or standard loops (forfor...of) to process array elements.
  • Combining Arrays: concat() merges two or more arrays into a new array without modifying the originals.
  • Sorting and Searching:
    • sort(): Sorts the elements of an array in place.
    • find(): Returns the value of the first element that satisfies a provided testing function.
    • includes(): Checks if an array contains a certain element and returns a boolean. 
Example of Javascript Arrays:

<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Arrays</h1>

<p id="demo"></p>

<script>
const cars = ["Saab", "Volvo", "BMW"];
document.getElementById("demo").innerHTML = cars;
</script>

</body>
</html>

Creating Arrays Using the JavaScript Keyword new
const cars = new Array("Saab""Volvo""BMW");

Changing an Array Element

This statement changes the value of the first element in cars:

cars[0] = "Opel";

Converting an Array to a String

The JavaScript method toString() converts an array to a string of (comma separated) array values.

Arrays are Objects

Arrays are a special type of objects. The typeof operator in JavaScript returns "object" for arrays.

But, JavaScript arrays are best described as arrays.

Arrays use numbers to access its "elements". In this example, person[0] returns John:

const person = ["John""Doe"46];

Array Methods:

Basic Array Methods(from w3schools.com)

Array length
Array toString()
Array at()
Array join()
Array pop()
Array push()
Array shift()
Array unshift()
Array isArray()
Array delete()
Array concat()
Array copyWithin()
Array flat()
Array slice()
Array splice()
Array toSpliced()

Full Stack Development- Class 4 - Variables, Data Types

 JavaScript uses variables as containers to store data values and is a dynamically typed language, meaning variable types are determined at runtime. Data is categorized into primitive and non-primitive types. 

Variables in JavaScript
Variables are declared using one of three keywords, each with different scoping and reassignment rules: 
  • var: Function-scoped (or globally-scoped) and can be updated and re-declared within the same scope. It is generally recommended to avoid var in modern JavaScript development in favor of let and const.
  • let: Block-scoped and can be updated but not re-declared within the same scope. This is the preferred way to declare variables whose values may change.
  • const: Block-scoped and creates a read-only "constant" that cannot be reassigned after its initial declaration. It must be initialized when declared. Note that while the variable itself cannot be reassigned, the properties of an object or elements of an array assigned to a const variable can still be modified. 

    Naming Rules
    • Names must begin with a letter, underscore (_), or dollar sign ($).
    • Names cannot begin with a number.
    • Names are case-sensitive (Boy and boy are different variables).
    • Reserved keywords (like ifforletconst) cannot be used as variable names. 


    Data Types in JavaScript
    JavaScript has eight data types, which are divided into two main categories: 
    Primitive Data Types
    These represent single, immutable values. 
    • String: Represents textual data, enclosed in single quotes ('...'), double quotes ("..."), or backticks (`...`).
    • Number: Represents numeric values, including integers and floating-point numbers. It also includes special values like Infinity and NaN (Not-a-Number).
    • Boolean: Represents a logical entity with only two possible values: true or false.
    • Undefined: A variable that has been declared but not assigned a value automatically has the value undefined.
    • Null: Represents an intentional absence of any object value. It is a special value that a programmer explicitly assigns.
    • Symbol: A unique and immutable primitive value, often used as an object key to avoid naming conflicts.
    • BigInt: Represents integers of arbitrary precision, larger than the maximum value a Number can safely hold. 

    Non-Primitive Data Type (Reference Type)
    The Object type is the only non-primitive type and is used for more complex data structures. When assigned to a variable, the variable holds a reference to the object's memory location, not the value itself.
    • Object: Collections of key-value pairs used to store structured data. E.g., let person = { name: "John", age: 30 };.
    • Array: A specialized type of object used to store ordered lists of values, accessed by an index (starting from zero). E.g., let fruits = ["Apple", "Banana"];.
    • Function: Functions are first-class objects in JavaScript and can be stored in variables, passed as arguments, and returned from other functions.