> Always use a BigInt (64 bits) or UUID for primary keys.
Use bigint, never UUID. UUIDs are massive (2x a bigint) and now your DBMS has to copy that enormous value to every side of a relation.
It will bloat your table and indexes 2x for no good reason whatsoever.
Never use UUIDs as your primary keys.
rowanseymour 4 hours ago [-]
And assuming we're not talking v7 UUIDs.. your indexes are gonna have objects you might commonly fetch together randomly spread everywhere.
gruez 4 hours ago [-]
>Use bigint, never UUID. UUIDs are massive (2x a bigint) and now your DBMS has to copy that enormous value to every side of a relation.
"enormous value" = 128 bits (compared to 64 bits)
In the worst case this causes your m2m table to double, but I doubt this has a significant impact on the overall size of the DB.
sgarland 3 hours ago [-]
When you have a few million rows, no. When you have hundreds of millions or billions of rows, yes, it matters very much.
TylerE 3 hours ago [-]
The concern isn’t the sign of the db on disc but doubling the size of all the indexes in memory
sgarland 3 hours ago [-]
Or if it’s MySQL, the PK is implicitly copied into every secondary index. Adds up quickly.
sgarland 3 hours ago [-]
I’ll go further; don’t automatically default to a BIGINT. Put some thought into your tables. Is it a table of users, where each has one row? You almost certainly won’t even need an INT, but you definitely won’t need a BIGINT. Is it a table of customer orders? You might need an INT, and you can monitor and even predict the growth rate. Did you hit 1 billion? Great, you have plenty of time for an online conversion to BIGINT, with a tool like gh-ost.
zerr 4 hours ago [-]
Wasn't UUIDs default go to types for primary keys in the .NET/SQL Server world even 20 years ago?
outside1234 4 hours ago [-]
If you don't have a natural primary key (the usual use case for UUIDs in distributed systems such that you can have a unique value) how do you handle that with bigints? Do you just use a random value and hope for no collisions?
benwilber0 2 hours ago [-]
You use a regular bigint/bigserial for internal table relations and a UUID as an application-level identifier and natural key.
hellojesus 4 hours ago [-]
Wouldn't you just have an autoincrementing bigint as a surrogate key in your dimension table?
Or you could preload a table of autoincremented bigints and then atomically grab the next value from there where you need a surrogate key like in a distributed system with no natural pk.
outside1234 4 hours ago [-]
Yes, if you have one database. For a distributed system though with many databases sharing data, I don't see a way around a UUID unless collisions (the random approach) are not costly.
bsder 3 hours ago [-]
> Never use UUIDs as your primary keys.
This seems like terrible advice.
For the vast, vast, vast majority of people, if you don't have an obvious primary key, choosing UUIDv7 is going to be an absolute no-brainer choice that causes the least amount of grief.
Which of these is an amateur most likely to hit: crash caused by having too small a primary key and hitting the limit, slowdowns caused by having a primary key that is effectively unsortable (totally random), contention slowdowns caused by having a primary key that needs a lock (incrementing key), or slowdowns caused by having a key that is 16 bytes instead of 8?
Of all those issues, the slowdown from a 16 byte key is by far the least likely to be an issue. If you reach the point where that is an issue in your business, you've moved off of being a startup and you need to cough up real money and do real engineering on your database schemas.
sgarland 3 hours ago [-]
The problem is that companies tend to only hire DB expertise when things are dire, and then, the dev teams inevitably are resistant to change.
You can monitor and predict the growth rate of a table; if you don’t know you’re going to hit the limit of an INT well in advance, you have no one to blame but yourself.
Re: auto-incrementing locks, I have never once observed that to be a source of contention. Most DBs are around 98/2% read/write. If you happen to have an extremely INSERT-heavy workload, then by all means, consider alternatives, like interleaved batches or whatever. It does not matter for most places.
I agree that UUIDv7 is miles better than v4, but you’re still storing far more data than is probably necessary. And re: 16 bytes, MySQL annoyingly doesn’t natively have a UUID type, and most people don’t seem to know about casting it to binary and storing it as BINARY(16), so instead you get a 36-byte PK. The worst.
benwilber0 2 hours ago [-]
> contention slowdowns caused by having a primary key that needs a lock (incrementing key)
This kind of problem only exists in unsophisticated databases like SQLite. Postgres reserves whole ranges of IDs at once so there is never any contention for the next ID in a serial sequence.
varispeed 4 hours ago [-]
Is it really enormous? bigint vs UUID is similar to talking about self-hosting vs cloud to stakeholders. Which one has bigger risk of collision? Is the size difference material to the operations? Then go with the less risky one.
rowanseymour 4 hours ago [-]
You shouldn't be using BIGINT for random identifiers so collision isn't a concern - this is just to future proof against hitting the 2^31 limit on a regular INT primary key.
gitroom 4 hours ago [-]
Pretty cool seeing how people still go for Django even with so many new frameworks, always makes me wanna go back to it when stuff gets messy tbh
fidotron 5 hours ago [-]
Are people choosing Django for new projects much these days?
sgt 5 hours ago [-]
Absolutely. For what it does, Django is pretty much the best full stack Python web framework there is. It's also a great way to rapidly develop (just sticking to synchronous, which Django is best at).
One can then later consider spinning certain logic off into a separate service (e.g. in Golang), if speed is a concern with Python.
pabe 5 hours ago [-]
Yes. Still one of the best batteries included web frameworks for creating anything that's more of a website (e.g. E-Commerce) than a web app (e.g. Photoshop). No, you don't need NextJs and friends for everything ;)
zerr 3 hours ago [-]
What would be the same that is for a statically typed language?
ecshafer 2 hours ago [-]
Play framework with Java or Scala is similar.
tcdent 4 hours ago [-]
I just rolled a backend using FastAPI and SQLAlchemy and it made me miss Django.
Too much other stuff going on in this app to incorporate Django, but it's still way ahead of the curve compared to bringing together independent micro frameworks.
thenaturalist 3 hours ago [-]
Out of naive curiosity of considering your first stack vs. Django: What makes Django so way ahead of the curve?
cjauvin 5 hours ago [-]
For a complete solution requiring many traditional high-level components like templating, forms, etc, then yes, clearly Django. But for something looking more like a REST API, with auto-generated documentation, I would nowadays seriously consider FastAPI, which, when used with its typed Pydantic integration, provides a very powerful solution with very little code.
wahnfrieden 5 hours ago [-]
Django Ninja?
macNchz 5 hours ago [-]
Works great, I've been using it in production for a few years. DRF was one of my least favorite bits of the Django world and Ninja has been an excellent alternative.
I still love Django for greenfield projects because it eliminates many decision points that take time and consideration but don't really add value to a pre-launch product.
seabrookmx 5 hours ago [-]
Not in my org. Though we did choose it for _one_ new project recently, mostly because we re-used some code from another Django project we had, and we wanted to lean on some readily available functionality from jazzband libs.
We have a few FastAPI services, but are mostly moving away from Python for projects > 1kloc.
nine_k 5 hours ago [-]
What are you moving towards? Node/TS? Golang?
ashwinsundar 5 hours ago [-]
I chose Django + htmx and a small amount of Alpine.js for a full-stack software project that is currently being launched. I had zero professional experience with Django (or Python really) before starting. I was able to develop the entire application on my own, in my spare time, and had time left over to also handle infrastructure and devops myself.
I prefer Python and it's web frameworks over Typescript/React because there is a lot more stability and lot less "framework-of-the-week"-itis to contend with. It's much easier to reason about Django code than any React project I've worked on professionally. IMO when you don't have a firehose of money aimed at you, then Python is the way to go
rowanseymour 4 hours ago [-]
If it's the kind of project that is going to run against one PostgreSQL database then I'd probably start a new project with Django just for its database migration support. That doesn't mean everything in the project has to be Django.
the__alchemist 4 hours ago [-]
You bet. Still the easiest (IMO) for websites, perhaps of any language.
ipaddr 4 hours ago [-]
It easy but having separate app spaces by default instead of just one like Laravel makes it slightly harder for just a website case.
the__alchemist 4 hours ago [-]
Concur. The multiple app paradigm doesn't fit any site I've built in Django. I make one called main.
hellojesus 4 hours ago [-]
Idk if it's best practice, but I usually like to make apps similar to components, where I have an app for accounts which handles user accounts, and a files app which handles all the dimension and fact tables around user uploads, and a social app for social features, etc.
It makes it easy to compartmentalize the business logic in terms of module imports.
JodieBenitez 5 hours ago [-]
yes
bnchrch 5 hours ago [-]
Just like Python itself, unfortunately yes.
ashwinsundar 4 hours ago [-]
Would love to hear an honest discussion of why Django and/or Python is a bad solution for any given problem. Is it because they are old technologies? Do they lack support for something in particular? Are they too expressive/not expressive enough?
the__alchemist 4 hours ago [-]
(Love django in spite of Python here)
- Imports are a mess
- No control of mutation in function signatures, and in general it's still a surprise when things mutate
- Slow
- Types and enums have room for improvement
blitzar 4 hours ago [-]
Because assembly language or if you must go higher level, fortran exist and all the 10x coding intergalactic scalers say everything else is bad.
tmnvix 3 hours ago [-]
Thanks for the summary. Looking forward to the videos becoming available.
> I talked to this speaker afterward, and asked him how they did nested modals + updating widgets in a form after creating a new object in a nested modal. He showed me how he did it, I've been trying to figure this out for 8 months!
Do share!
flakiness 4 hours ago [-]
It looks like htmx is popular in the Django community. Is there any background story that made this? (Context: Just picked Django for a hobby project. Don't know much about Webdev trend beyond, like, what are talked about on the HN top page.)
wahnfrieden 4 hours ago [-]
Server side template rendering is popular already and well supported in Django ecosystem
neural_embed 5 hours ago [-]
Some of the talks look really interesting — are there any YouTube videos linked? I couldn’t find those.
SCUSKU 4 hours ago [-]
The conference coordinators said they would be released in about a month, so I will update the post once they are released! I am really excited to watch them again. Amazingly informative stuff.
Use bigint, never UUID. UUIDs are massive (2x a bigint) and now your DBMS has to copy that enormous value to every side of a relation.
It will bloat your table and indexes 2x for no good reason whatsoever.
Never use UUIDs as your primary keys.
"enormous value" = 128 bits (compared to 64 bits)
In the worst case this causes your m2m table to double, but I doubt this has a significant impact on the overall size of the DB.
Or you could preload a table of autoincremented bigints and then atomically grab the next value from there where you need a surrogate key like in a distributed system with no natural pk.
This seems like terrible advice.
For the vast, vast, vast majority of people, if you don't have an obvious primary key, choosing UUIDv7 is going to be an absolute no-brainer choice that causes the least amount of grief.
Which of these is an amateur most likely to hit: crash caused by having too small a primary key and hitting the limit, slowdowns caused by having a primary key that is effectively unsortable (totally random), contention slowdowns caused by having a primary key that needs a lock (incrementing key), or slowdowns caused by having a key that is 16 bytes instead of 8?
Of all those issues, the slowdown from a 16 byte key is by far the least likely to be an issue. If you reach the point where that is an issue in your business, you've moved off of being a startup and you need to cough up real money and do real engineering on your database schemas.
You can monitor and predict the growth rate of a table; if you don’t know you’re going to hit the limit of an INT well in advance, you have no one to blame but yourself.
Re: auto-incrementing locks, I have never once observed that to be a source of contention. Most DBs are around 98/2% read/write. If you happen to have an extremely INSERT-heavy workload, then by all means, consider alternatives, like interleaved batches or whatever. It does not matter for most places.
I agree that UUIDv7 is miles better than v4, but you’re still storing far more data than is probably necessary. And re: 16 bytes, MySQL annoyingly doesn’t natively have a UUID type, and most people don’t seem to know about casting it to binary and storing it as BINARY(16), so instead you get a 36-byte PK. The worst.
This kind of problem only exists in unsophisticated databases like SQLite. Postgres reserves whole ranges of IDs at once so there is never any contention for the next ID in a serial sequence.
One can then later consider spinning certain logic off into a separate service (e.g. in Golang), if speed is a concern with Python.
Too much other stuff going on in this app to incorporate Django, but it's still way ahead of the curve compared to bringing together independent micro frameworks.
I still love Django for greenfield projects because it eliminates many decision points that take time and consideration but don't really add value to a pre-launch product.
We have a few FastAPI services, but are mostly moving away from Python for projects > 1kloc.
I prefer Python and it's web frameworks over Typescript/React because there is a lot more stability and lot less "framework-of-the-week"-itis to contend with. It's much easier to reason about Django code than any React project I've worked on professionally. IMO when you don't have a firehose of money aimed at you, then Python is the way to go
It makes it easy to compartmentalize the business logic in terms of module imports.
- Imports are a mess - No control of mutation in function signatures, and in general it's still a surprise when things mutate - Slow - Types and enums have room for improvement
> I talked to this speaker afterward, and asked him how they did nested modals + updating widgets in a form after creating a new object in a nested modal. He showed me how he did it, I've been trying to figure this out for 8 months!
Do share!