Written by

Senior Startups and Community Programs Manager at InterSystems Corporation
Discussion Evgeny Shvarov · Jun 21, 2025

CreatedAt and LastUpdated - do you use it?

Hi fellow developers!

Curious if you guys use CreatedAt and LastUpdated properties in your classes?

Created to stamp when the record was created and LastUpdated when it was last updated. Where it can be useful - almost everywhere )) I find it convenient in records sorting (e.g. by creation or last update), in sync (with other systems), and so on, for better analytics.

Do you use it all the time for all the classes?

If don't, why not? What do you use instead?

What property type do you use - %TimeStamp? %DateTime?

What is the best practice to have CreatedAt filled automatically during creation and LastUpdated on every successful save (guess it could be in %OnSave)?

Please share your experience /thoughts?

Which properties do you use in your persistent classes
0%
(0 votes)
CreatedAt
0%
(0 votes)
LastUpdate
100%
(12 votes)
Both
0%
(0 votes)
Don't see why should I
0%
(0 votes)
Use something else
Total votes: 12
This poll is closed.

Comments

Andrew Sklyarov · Jun 21, 2025

I believe it is a good way if you use ORM:

Property CreatedAt As %TimeStamp [ InitialExpression = {$ZDATETIME($HOROLOG, 3)}, Required ];
0
Evgeny Shvarov · Jun 24, 2025

Just've published the shvarov-persistent package once installed by
USER>zpm "install shvarov-persistent"

will add shvarov.persistent.base class which can be used as an ancestor after %Persistent, like:

Class yourclass Extends (%Persistent, shvarov.persistent.base)

, which will add two properties:

Property CreatedAt As %TimeStamp [ InitialExpression = {$ZDT($H, 3)} ];

Property LastUpdate As %TimeStamp [ SqlComputeCode = {set {*}=$ZDATETIME($HOROLOG,3)}, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];
0
David Hockenbroch  Jun 26, 2025 to Evgeny Shvarov

Whoops, I replied to the wrong comment somehow. Sorry!

Edit: for some reason when I clicked on the Reply button on Evgeny's comment above, it was initially showing this reply under Sergei's post below. Then when I left the page and came back, it was in the right place. Firefox being weird on me, I guess.

0
David Hockenbroch  Jun 26, 2025 to Evgeny Shvarov

I have done those two, plus in certain cases a "CreatedBy" and "LastUser" that are automatically computed to the $USERNAME in insert and on insert/update.

0
Evgeny Shvarov  Jun 26, 2025 to David Hockenbroch

like LastUser property too - seems helpful

0
Steve Pisani  Jul 1, 2025 to Evgeny Shvarov

As this stands, isn't it possible for developers to accidentally SET the CreatedAt property?.  I think it is best if this was read only, to avoid bad code accidentally corrupting this field.

0
Evgeny Shvarov  Jul 1, 2025 to Steve Pisani

I agree. I changed it to "not read-only" as I wasn't to manage unit-tests without it :) 

Don't know how to mark an object "modified" - otherwise, %Save() doesn't trigger the calculated property to update.

But I agree - read only is much better.

0
Sergei Shutov · Jun 26, 2025

Yes we usually use both, but naming should be consistent - I like DtCreated and DtUpdated because it will sort close together, but CreatedAt and UpdatedAt will do as well

0
Ben Spead  Jun 26, 2025 to Sergei Shutov

I really like that idea, having them close together is extremely helpful. We always use the created and updated properties as well, with %OnAddToSaveSet() triggers for both

0
Evgeny Shvarov  Jun 26, 2025 to Ben Spead

@Ben Spead it's great you mentioned %OnAddToSaveSet() triggers - how do you manage cases when records were changed by CREATE/UPDATE SQL query? These triggers not fire in this case, right?

0
Evgeny Shvarov  Jun 26, 2025 to Sergei Shutov

Great idea on DtCreated DtUpdated naming

0
Robert Barbiaux  Jun 26, 2025 to Evgeny Shvarov

In interop Ens.MessageHeader, we have TimeCreated and TimeProcessed. I would along the same lines and have TimeCreated and TimeUpdated. I find Time… more appropriate as those are time stamps, not dates.

0
Dan Pasco · Jun 26, 2025

The compute triggers, %%INSERT and %%UPDATE are, in my opinion the best option. They are specifically supported for this purpose and are completely seamless between SQL and Objects. Callbacks and other options may not be seamlessly supported by both filers.

0
Evgeny Shvarov  Jun 26, 2025 to Dan Pasco

Thanks @Daniel.Pasco. This is what I used in the example class.

Yes, it's great that we have it now in IRIS.

0