Which is larger in byte size? "Nat64" or "?Nat64"?

what about 0: Nat64 vs null: ?Nat64 ?

nvm i tested it on icpninja

let a : Nat64 = 0;
let b : ?Nat64 = null;
let c : ?Nat64 = ?0;

let x = to_candid(a);
let y = to_candid(b);
let z = to_candid(c);

let a_size = x.size();
let b_size = y.size();
let c_size = z.size();
return debug_show ({ a; b; c; a_size; b_size; c_size });

result:

("{
  a = 0; a_size = 15; 
  b = null; b_size = 10; 
  c = ?0; c_size = 18
}")

is it a good idea to store expires_at: Nat64 and set it to 0 to represent Never expires ?

note: on the query/update function, the arg type will be expires_at: ?Nat64.

Are you asking about ingress byte size, i.e. when candid encoded in canister calls arguments?

Or are you asking about Motoko in-memory (heap) byte size?

Seems to be the first because of the example code you posted, but just wanted to confirm.

i was asking about storing data inside canister and just wondering if it’s better to store absolute type rather than optional type, then use sentinel value like 0 to represent null

Optional values are stored very efficiently in memory (heap) by Motoko: