Hey everyone! π
Iβm a Node.js backend developer who worked mostly with MongoDB. Recently I shifted to SQL databases β and the first unexpected challenge I faced wasβ¦
π BigInt. Yes, you heard that right.
SQL databases like MySQL/PostgreSQL often use BIGINT for primary keys and timestamps, especially when dealing with large IDs or auto-increment values.
Everything was fine until I fetched or created data and tried to return it through:
res.status(200).json(data);
Boom. β Node.js threw this error:
TypeError: Do not know how to serialize a BigInt
This is where my debugging journey started.
β Why Does JSON Refuse BigInt?
Hereβs the important part:
JSON does NOT support BigInt.
JSON only supports:
- string
- number
- boolean
- null
- object
- array
BigInt is not included. So when we do res.status(200).json({data:createdUser}) Express internally does: JSON.stringify(data)
β¦it fails because:
JSON.stringify({ id: 123n });
// β Throws error
π My First Solution (Manual Conversion)
Initially, I wrote a utility function that walked through my object and converted any BigInt to a string.
Something like:
function convertBigInt(obj) {
// check object values and convert BigInt β string
}
But this had 3 major problems:
- Needed to call it manually on every response
- Nested objects became difficult
- Extra processing on every endpoint
So I needed a better, global solution.
π The Cleanest Fix: Overriding BigInt Serialization Globally
Here is the solution that solved everything in one line:
const setupBigIntSerialization = () => {
BigInt.prototype.toJSON = function () {
return this.toString();
};
};
What does this do?
Whenever JSON.stringify() encounters a BigInt,
it calls .toJSON() if it exists.
So now:
JSON.stringify({ id: 123n });
returns:
{ "id": "123" }
β No error
β No precision loss
β No need for manual conversion
β Works for all Express responses
π How to Use This in Your Project
Step 1: Create a utility file
utils/bigintSerialization.js
const setupBigIntSerialization = () => {
BigInt.prototype.toJSON = function () {
return this.toString();
};
};
export default setupBigIntSerialization;
Step 2: Call this function in your entry file
In server.js or app.js:
import setupBigIntSerialization from "./utils/bigintSerialization.js";
setupBigIntSerialization(); // enable BigInt β string globally
Step 3: Done.
Now every res.json()will safely serialize BigInt values without crashing your API.
β οΈ Why Not Convert BigInt to Number?
Because itβs unsafe.
If you do:
Number(123456789012345678901n);
You will lose precision because JavaScript number uses double-precision floating point.
Thatβs why the correct, safe approach is converting BigInt β string, not BigInt β number.
π§ Bonus: Why This Works Internally
This is the part that helped me fully understand whatβs going on.
Express uses JSON.stringify()
JSON.stringify() checks if the value has a .toJSON() method
If yes β it uses the return value of .toJSON()
So we override BigIntβs default .toJSON()
Now BigInt becomes JSON-safe automatically everywhere
This is the same mechanism that JavaScript uses for:
Date
Map
Set
Custom classes
π’ Final Result
After adding that one tiny helper, everything worked smoothly:
- No more BigInt errors
- No more manual conversions
- Cleaner backend code
- Safe for all routes and all responses
π Final Thoughts
If youβre moving from MongoDB to SQL or using ORMs like Prisma, Sequelize, TypeORM, etc., you will eventually deal with BigInt values.
This small utility makes your entire API BigInt-proof with almost no effort.
I hope this post helps you the same way this fix helped me.
If you have any questions or want me to write a part-2 explaining JSON.stringify and serialization in depth β comment below!
Happy coding! π
Top comments (0)