Search code examples
web-applicationsthree-tier

Is it bad to specify "id" and "created_at" values within the FrontEnd app?


I am writing a Flutter application that has a built-in null-safety feature requires me to initialize variables at the creation time or tag it as a nullable variable like below:

String? id;
DateTime? created_at;

Or even on my NodeJS TypeScript backend application, it needs the undefined type to be considered if we don't want to initialize the variable, like below:

id?: string;
created_at?: Date;

I am just wondering to know is it a bad idea if I initialize this variables before I insert them inside the database(Cassandra or MySQL), instead of letting the database create those id and created_at variables automatically by either defining them in TABLE schemas(for MySQL) or in a CQL command(foe Cassandra), like following:

MySQL:

  id INT AUTO_INCREMENT UNIQUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

Cassandra:

INSERT INTO table_name (id, created_at)
VALUES (uuid(), toTimestamp(now()));

Solution

  • If I understand your question correctly, there are 3 places where you can potentially set this data: frontend, webserver and database. Lets discuss each option:

    (1) Frontend: This option is bad or very bad. You basically allow users to tamper the data. How this can affect you depends on what you do with the data. For example consider the situation where you have VOD service, and users pays depending on how much video they watch. You measure this by gathering "I watched 5s of XYZ" logs. Each log has created_at date, which then you query to calculate how much the user should pay. A malicious user can now modify the date and set it to, say year 2300. You've just allowed users to watch your content for free.

    On the other hand setting id on the frontend, which should be unique, will be either extremely difficult or extremely inefficient (which additionally opens road for DDOS). So you have both hard and unsafe solution now. Just don't do this.

    Change your design: no design or good practice should ever make the app insecure. Especially such basic things like null safety. If it leads to an insecure solution then get rid of it. Or apply it in a different way.

    The next two are both ok options with advantages and disadvantages each.

    (2) WebServer: setting it here has an obvious advantage that database doesn't have to do this. Since it is typically easier to scale webserver than database, it might be important under heavy load, although lets be honest: autoincrementing a counter is typically a very fast operation. The biggest disadvantage is that if you want to keep the id field autoincrementing, then it is hard without some central support. That being said, it is rarely the case that we actually need id to be autoincrementing. Using UUIDs instead is a well known technique that avoids this issue.

    (3) Database: this has the advantage that you can easily use autoincrementing field, if a database supports it. This is the case for MySQL, not for Cassandra unfortunately (although it can be emulated, google it). The disadvantage is that it slows down the database. It will be barely noticable for MySQL, but for Cassandra it is a different story (although uuid() call won't be noticable).

    Timestamp can be easily and safely set by webserver, as long as your clocks are synced (if you use more than one machine) and you use a consistent method of time generation/serialization (e.g. linux timestamps).

    The rule of thumb that I use is: if I can do something with a webserver instead of database, and it is not insanely hard, then I will move it to the webserver.