Should I use dual validation layers for both application logic and database constraints?

I’m working on a REST API and wondering about the best approach for data validation. I want to make sure I’m doing things right when it comes to checking data both in my application code and at the database level.

Here’s my setup - I have an article table:

id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
author_id UUID REFERENCES authors(id) NOT NULL

And a comments table:

id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
author_id UUID REFERENCES authors(id) NOT NULL,
article_id UUID REFERENCES articles(id) NOT NULL,
text VARCHAR(300)

I need to limit how many articles each author can create and also limit the comments per article. I can either use database constraints or check these limits in my backend code before inserting data. Which approach is better? Should I use both methods for extra safety or is that overkill? When does it make sense to have this kind of double checking?

honestly, I’d start with db constraints - they’re your final defense against bad data. app-level checks help with ux but can fail or get bypassed. running both isn’t overkill, especially for business-critical stuff like article limits.

Database constraints are your last line of defense, but app-level validation gives users a better experience and faster responses. I always do both since they handle different things. App validation catches problems early - you can send back helpful error messages without even touching the database. Database constraints keep your data clean even when your app code breaks or someone bypasses it entirely. For article and comment limits, I’d use triggers or stored procedures on the database side plus your API validation. This combo has saved my ass from data corruption so many times when bugs made it past testing. The extra work is nothing compared to the protection you get.

what’s the performance hit with this dual approach? does checking limits in app code first actually save db resources, or is the overhead not worth it? and how do u handle race conditions when multiple requests come in at the same time?