Thanks for the suggestion. Objo strings are indeed backed by .NET strings, so exposing interning is a good fit here.
I’ve added String.Intern() for the next release (https://feedback.objo.dev/feature/434). It returns the exact string value from the process-wide intern pool, so this will work well for bounded repeated values like state codes, status names, categories, etc.
One important detail: Intern() does not normalise the string. So "az".Intern() and "AZ".Intern() are separate interned strings, even though Objo string comparisons are case-insensitive by default. If you want canonical storage, normalise explicitly first:
state = state.Trim().Uppercase().Intern()
I’ve also documented the usual caveat: interned strings remain in the intern pool for the lifetime of the app, so this should be used for bounded vocabularies rather than free text, GUIDs, timestamps, URLs, or other mostly-unique values.