What is a timelock on Bitcoin?
Let’s start with the basics. A timelock is a smart-contract primitive that attaches a time condition to a spending path: a rule that says “this spend is only valid from a certain moment onward”. Despite the name, it doesn’t lock your coins away. Think of it less as a lock on your money and more as a time-based clause in the rules for spending it.
So what happens if you try to spend it early? The network simply refuses the transaction, because this is a consensus rule. Once the timelock’s moment has arrived, the very same spend goes through normally.

Two different types of timelock
Programming time into Bitcoin can be done in two ways, either with an absolute timelock or with a relative timelock.
The absolute timelock can be pictured as a calendar. You write down an appointment, say January 1, 2032. When the day comes, the alarm goes off. Whatever happened between today and that date is irrelevant, the appointment is set in stone once and for all. That’s the absolute timelock: it points to a fixed instant, the same for everyone, marked on the timeline.
The relative timelock can be pictured as an hourglass. You flip it at the exact moment the coin lands in your wallet, and the sand starts running from that instant. If the coin moves again, the first hourglass is forgotten, you grab a new one and the countdown restarts from zero. That’s the relative timelock: it doesn’t measure a specific date but a duration elapsed since an event (the moment the coin was received).

Where the lock lives: in the transaction or in the script?
Before detailing how each type of timelock works, we need to understand a second distinction, orthogonal to the first. A timelock can sit in two different places.
The first place is the transaction itself. A Bitcoin transaction has fields meant for this: nLockTime for the absolute timelock, nSequence for the relative timelock. By filling them in, you attach a time condition to that specific transaction, which amounts to having it say “I won’t be valid until such a moment, or until such a duration has passed since my coins were received”.
The problem is that a condition carried by the transaction doesn’t protect the coins. As long as a transaction isn’t confirmed in a block, it doesn’t really exist on Bitcoin, so it imposes no constraint on the funds it would like to spend.
Here’s an example: suppose Alice hands you a transaction timelocked until next year. Nothing stops her, in the meantime, from building another transaction that spends the same coins, this time with no timelock, and broadcasting it right away. If that second transaction confirms on the blockchain, the locked version you were holding becomes void. In other words, a timelock placed on a transaction alone stops no one from spending their coins early: it describes a constraint on a passing transaction, not on the coin itself.

To get a genuine guarantee, you therefore have to carve the timelock one level deeper, into the coin’s script, that is, into the UTXO’s spending conditions. That’s the job of two opcodes: OP_CHECKLOCKTIMEVERIFY, often shortened to CLTV, for the absolute timelock, and OP_CHECKSEQUENCEVERIFY, often shortened to CSV, for the relative timelock. With these opcodes, the time condition is written into the coin. Any transaction that wants to spend it, whatever it is, will be forced to respect it, and there’s no longer any way to craft a version without a timelock, since the constraint comes from the coin and not from the goodwill of whoever spends it.
So we have two scopes, the transaction and the script, and two types, absolute and relative:

But be careful: these aren’t four independent mechanisms. The two levels are complementary. A lock placed on a transaction alone secures nothing, as we just saw. And a lock written into a script doesn’t work on its own either: the opcode never checks the clock, it only requires that the transaction spending the coin declare a valid nLockTime or nSequence. It’s this field, at the transaction level, that the network actually compares against the time or the block height. Each type of timelock is therefore a pair: a transaction field and a script opcode.
For what follows, keep in mind that nLockTime and CLTV are the two mechanisms of the absolute timelock, while nSequence and CSV are the two mechanisms of the relative timelock. We’ll now take each type of timelock separately and see exactly how it works.

The absolute timelock
As we saw earlier, the absolute timelock designates a fixed moment before which spending is impossible. That’s what we captured with the calendar metaphor.
On the transaction side, the field responsible is called nLockTime. It’s a 4-byte field present in every Bitcoin transaction, and it has existed since the very beginning of the protocol. It states the earliest block height, or date, at which the transaction may enter a block.
Here’s an example: Alice sets the nLockTime of her transaction to 1,000,000. She can sign and broadcast it today, while the chain is at block 950,000, but the network refuses it: no miner can include it until height 1,000,000 is reached. The day that block is mined, the transaction becomes valid and can finally enter the chain. I’ve used block height here for the example, but you can also choose a date instead.

On the script side, the opcode OP_CHECKLOCKTIMEVERIFY (CLTV) completes the setup. It acts through a cascade of two restrictions. First, CLTV restricts the values allowed for the nLockTime field of the transaction that wants to spend the coin: it requires that this nLockTime be at least equal to the value written in the script. Then that nLockTime field, in turn, restricts the moment the transaction can enter a block, since it’s the one that carries the absolute timelock, as we just saw. Chaining the two together gives you the guarantee you want.
If Alice holds a coin with an OP_CHECKLOCKTIMEVERIFY set to 1,000,000, any transaction that spends the coin will have to declare an nLockTime of at least 1,000,000, otherwise the script fails, and that nLockTime in turn prevents the transaction from being mined before block 1,000,000.
The script constrains the transaction’s field, and the field constrains the moment of inclusion.

Unlike the nLockTime field, the CLTV opcode didn’t exist at Bitcoin’s launch. It was added by BIP-0065, through a soft fork of its own, activated on December 14, 2015.
In a sense, the two pursue opposite goals. nLockTime prevents a transaction dated in the future from entering the chain too early, whereas CLTV makes a coin spendable only after a given moment, precisely by forcing the spending transaction to carry such an nLockTime. The nLockTime is freely chosen by whoever builds the spending transaction: you can therefore place an nLockTime on the spend of any coin, at the moment you spend it. CLTV, on the other hand, is carved into the script when the address is created, and no one can change it afterward. That’s what turns a reversible “I choose to wait” into a “the coin forces me to wait” that can’t be bypassed.
Expressing time in an absolute timelock
That leaves how time is expressed. Bitcoin accepts two units for this:
- A block height. For example “not before block
1,000,000”. The transaction becomes valid once the chain reaches that height. - A date. For example “not before January 1, 2032”. The transaction becomes valid once that moment has passed.
You might then wonder how Bitcoin tells the two apart, since both are just numbers. Through a single threshold equal to 500,000,000. If a timelock has a value below 500,000,000, the number is read as a block height. From that value up, it’s read as a date, and more precisely as a Unix timestamp, that is, the number of seconds elapsed since January 1, 1970 at 00:00:00 UTC. For example, the value 1,956,528,000 corresponds to January 1, 2032 at midnight: a transaction carrying that nLockTime can’t be mined before that date.

When the timelock is expressed as a block height, it’s fairly simple to compare, since the height is a fixed figure, the same for everyone, that can’t be manipulated because each block arrives strictly in sequence. When the timelock is expressed as a date, however, it’s more complex, because there are different notions of time, the whole network may not share exactly the same clock, and above all, block timestamping rules are fairly flexible for miners. So we don’t compare it against the timestamp the miner writes into the header of their block, but rather against the median time of the last 11 blocks, what’s called the “MTP” (Median Time Past).
In practice, when validating a block, you take the timestamps of the 11 blocks preceding it, sort them, and keep the middle one. A transaction locked this way can only enter that block if its nLockTime is strictly below this median.

This rule comes from BIP-0113, activated in July 2016, and fixes a perverse incentive. Before it, the comparison was made against the block’s own timestamp, a field a miner can push up to roughly two hours into the future: they therefore had an incentive to lie about the time, so as to include transactions whose lock hadn’t yet matured and pocket their fees. The MTP, by contrast, can only move forward, never backward, and skewing it requires controlling at least 6 of the last 11 blocks, which makes date-based timelocks far more predictable.
One last detail: the median roughly corresponds to the block mined one hour earlier, so the lock in our example, set to January 1, 2032 at midnight, will in practice only open around 1 a.m.

The limits of the absolute timelock
One characteristic of the absolute timelock is that it has a very distant ceiling in block height, since you can aim up to roughly 9,500 years into the future. This figure follows directly from the 500,000,000 threshold seen above: since any lower number is read as a block height, the most distant expressible height is 499,999,999. A block is found on average every 10 minutes, so 500 million blocks represent about 5 billion minutes, that is, roughly 9,500 years.
This headroom only holds for block-height mode, though. In date mode, nLockTime shares the limit of Bitcoin’s timestamp fields, which are unsigned 32-bit integers. The available date range therefore extends at most to February 7, 2106, at 06:28:15 UTC.

What OP_CLTV does
Now that we’ve grasped the broad principles of the absolute timelock, let’s look more precisely at what the CLTV opcode does.
When OP_CHECKLOCKTIMEVERIFY runs on the stack, it fails and makes the script impossible to satisfy in several cases:
- if the stack is empty (the opcode has to read a value at the top to compare it, without one it has nothing to check),
- if the value at the top is negative (a block height or a date can’t be negative, since a negative timelock is impossible),
- if its type (height or date) doesn’t match that of the transaction’s
nLockTime(comparing a block height to a date would make no sense), - if this value exceeds the declared
nLockTime(this is the heart of the timelock: the transaction must announce annLockTimeat least equal to the value written in the script, otherwise it claims to be able to spend too early), - or if the
nSequenceof the spending input is0xFFFFFFFF(this value neutralizes the transaction’snLockTime).
This last point matters. nLockTime is only enforced if at least one input of the transaction carries a non-final nSequence, that is, a value below 0xFFFFFFFF. If every input were left at 0xFFFFFFFF, the nLockTime would be disabled, and the recipient of a timelocked coin could spend it ahead of time. CLTV therefore fails deliberately when the nLockTime is neutralized this way. In theory, a non-final nSequence on any single input of the transaction would have been enough, but BIP-0065 requires that the input spending the CLTV output itself carries a non-final nSequence, so the rule can be checked by looking at that input alone, without scanning the rest of the transaction.
We find here, in passing, a rule against mixing timelock types (time vs. block height) carved right into the opcode. The type of the timelock written in the script must therefore match that of the nLockTime.

You already use nLockTime without knowing it
The absolute timelock has another use, invisible to the user, that has nothing to do with delaying a spend into the future. Since late 2014, the Bitcoin Core wallet, followed by others, writes by default into every transaction an nLockTime equal to the current block height. Not to delay anything, but to discourage an attack called “fee sniping”.
As the block reward shrinks over successive halvings, and miners’ revenue rests more and more on fees, the contents of an already-mined block can become a profitable target. A miner might be tempted, instead of mining at the chain’s tip, to re-mine the last block and trigger a reorganization to grab its potentially large fees and the best transactions waiting in the mempool. Currently, in 2026, a miner avoids going backward, because the subsidy makes up a large share of their revenue, and their fee-sniping block risks becoming stale (with no child block) and therefore earning them nothing. But if a block is exceptionally rich in fees, the risk might be worth it.
This is where nLockTime comes into play. If everyone stamps their transactions with the current block height, then a freshly broadcast transaction can only enter the next block, not a past block someone would try to re-mine. A miner going backward therefore couldn’t include these new transactions, which reduces the potential profitability of fee sniping accordingly and keeps mining at the tip worthwhile.

The relative timelock
The relative timelock doesn’t designate a precise moment, but a delay triggered from the confirmation of the coin being spent. It’s the hourglass metaphor, the one you start at the moment the funds are received.
On the transaction side, the field responsible for the relative timelock is nSequence. Note that there’s an important structural difference here: nLockTime is a single field, shared by the entire transaction, whereas nSequence sits in each of the inputs. For example, a transaction spending 3 UTXOs carries a single nLockTime, but 3 nSequence fields.

Like nLockTime, nSequence does operate at the transaction level, not the script level: when you sign the spend, you write into it the minimum delay that must have elapsed since the coin spent by the input was confirmed, a delay expressed in blocks or in wall-clock time (as for absolute timelocks). And even though each input sets its own delay this way, the relative timelock commits the whole transaction: it only takes one timelocked input that isn’t old enough yet to make the entire transaction invalid.
On the script side, the opcode OP_CHECKSEQUENCEVERIFY (CSV), introduced by BIP-0112, carves the delay into the coin itself when the funds are received, so that it can no longer be changed at spending time.
These additions, plus the use of MTP, were activated together by a soft fork on July 4, 2016, through BIP-0068, BIP-0112, and BIP-0113. Be careful not to fold
CLTVinto this fork: that opcode had already been live since December 2015, through BIP-0065 and a separate soft fork of its own. OnlyCSVarrived with this July 2016 fork. Both opcodes were deployed the same way, though, by recycling opcodes with no effect.CLTVtook the place of the oldOP_NOP2back in 2015,CSVthat of the oldOP_NOP3in 2016. AnOP_NOPis an opcode kept deliberately inert when the script runs it: it doesn’t touch the stack and changes nothing, it simply moves on to the next instruction. Bitcoin reserves a whole series of them, fromOP_NOP1toOP_NOP10, precisely to serve one day as anchor points for new rules. Thanks to this, an old node simply ignores the new timelock condition, checks only the signature, and accepts the transaction. An up-to-date node, on the other hand, runs the real logic in the same place. It compares the stack value against the relevant transaction field (nLockTimeforCLTV,nSequenceforCSV), and makes the script fail if the condition isn’t met. It’s the same script but with two different readings. One ignores the timelock, the other enforces it, but if the timelock is respected, both accept the transaction.

This is precisely what defines a soft fork. The new rule only adds a constraint, it tightens what’s valid without ever broadening it. Everything an up-to-date node accepts, an old node accepts too. This kind of change therefore stays safe as long as a majority of the hashrate enforces it. If a minority of miners produced blocks violating the rule, the chain that respects it would eventually outpace them, and even old nodes would rally to it, since both chains look equally valid to them.
Expressing time in a relative timelock
The relative timelock’s delay is expressed, here too, in two possible units:
- A number of blocks since the coin’s confirmation. For example “not before 52,560 blocks after receipt” (= about one year).
- A wall-clock duration, in slices of 512 seconds since the confirmation.
The block-based rule is very simple to grasp. If a coin is confirmed at block n and its script imposes a relative CSV timelock of value s, then it becomes spendable at block n + s, not before.

The relative timelock mechanism also rests on a cascade of two constraints:
CSVrequires that thenSequenceof the input spending the coin be at least equal tos, otherwise it fails,- and that
nSequence, in turn, requires that the transaction can’t enter a block before heightn + s.
The script constrains the input, and the input constrains the transaction. The delay value is carved into the coin’s script at its creation, that is, when the funds are received, but the nSequence that satisfies it is set on the transaction’s input, so at spending time.

The time-based relative timelock is slightly more complex to grasp. First, the value written doesn’t count seconds one by one, but slices of 512 seconds. A timelock of value s therefore requires waiting 512 times s seconds. For example, to impose about 24 hours of timelock, you write the value 169, that is, 169 slices of 512 seconds, which give 86,528 seconds, a little over a day.
Then, to measure this duration, the network uses the MTP. The stopwatch starts at the MTP observed when the coin was confirmed (more precisely, BIP-0068 uses the MTP of the block preceding its own), and the spend only becomes includable once the chain’s current MTP overtakes that starting point by the required delay. Note that both bounds rely on the same MTP clock: its roughly one-hour lag behind real time weighs as much on the start as on the finish, and therefore cancels out over the measured duration.

Anatomy of the nSequence field
The nSequence field is 32 bits, but the relative timelock uses only part of it. The most significant bit, at position 31 (1 << 31), is a disable flag: as long as it’s 1, the input has no relative timelock. The bit at position 22 (1 << 22, that is 0x400000) is a type flag, which indicates whether the value is read in blocks or in slices of 512 seconds. Finally, the 16 low-order bits carry the delay value, which caps it at 65,535 units.

An input’s relative timelock is therefore active under two conditions:
- that the transaction be version 2 or higher,
- and that this input’s disable bit be 0, that is, that the
nSequencebe below0x80000000.
You might be wondering why this disable flag exists, if the version is enough to disable timelock verification. It’s because if a future version 3 brought other features, you might want to take advantage of them without being subject to the relative timelock, and bit 31 is precisely what lets you neutralize it on demand.
You might also be wondering why the time mode counts in slices of 512 seconds rather than in seconds. Well, because 16 bits would only cover 2¹⁶ seconds, that is, about 18 hours, which is far too short for most uses. By multiplying by 512, you extend the timelock’s reach in time to about 388 days, where the block-based timelock reaches about 15 months (512 simply being the power of 2 closest to the 600 seconds of the average interval between two blocks).
Let’s take an example to make it clear: an input whose nSequence is 0x00000090 carries a block-based relative timelock, because the type flag is 0, and its value is 0x90, that is, 144 in decimal. The coin spent in this input must therefore be at least 144 blocks old, that is, about one day.
If you set the type flag, for example with 0x00400007, you switch to seconds: the value 7 is multiplied by 512, that is, 3,584 seconds, a little less than an hour of timelock.

This nSequence field is rather special in Bitcoin, because it doesn’t serve only relative timelocks. Depending on its value, it can control three features tied to a transaction’s finality:
- With a value of
0xFFFFFFFF(that is, its maximum value) the input is said to be final: no relative timelock, no RBF signaling, and the transaction’snLockTimeis even neutralized. With a value of0xFFFFFFFEor below, the transaction’snLockTimeis taken into account. - With a value of
0xFFFFFFFDor below, the input additionally signals that it accepts BIP-0125 replace-by-fee (RBF). - Finally, as soon as the disable bit drops to 0, the input carries a relative timelock, provided the transaction is version 2.
By default, the Bitcoin Core wallet long set 0xFFFFFFFE, which activates the nLockTime and nothing else. Since its version 24.0, in late 2022, it also signals RBF by default, and therefore sets 0xFFFFFFFD. Note that there’s an asymmetry here: activating the nLockTime or RBF is decided at the scale of the whole transaction, a single input below the threshold is enough, whereas the relative timelock is set input by input. And since a relative timelock’s value is inherently low, such an input activates the nLockTime and signals RBF at the same time.

What OP_CSV does
Let’s now look more precisely at what the CSV opcode does on the stack.
When OP_CHECKSEQUENCEVERIFY runs on the stack, it fails and makes the script impossible to satisfy in several cases:
- if the stack is empty (the opcode has to read a value at the top to compare it, without one it has nothing to check),
- if the value at the top is negative (a timelock can’t have a negative waiting delay, that makes no sense),
- if the transaction is version 1, and therefore has no relative timelocks (consensus only reads
nSequenceas a delay from version 2 onward, in version 1 the timelock wouldn’t be enforced, andCSVrefuses to validate a guarantee that wouldn’t be one), - if the input’s
nSequencehas its disable flag raised, that is, if the input declares no relative lock (with no lock declared by the input, no delay would actually be applied to the spend), - if the lock type (blocks or time) doesn’t match between the script value and the
nSequence(comparing blocks to seconds would make no sense, both must share the same unit), - or if the lock value written in the script exceeds the one the
nSequencedeclares (this is the heart of the timelock: the input must announce a delay at least equal to the one carved into the script, otherwise it claims to spend before term).
By contrast, if the value placed in the script itself carries the disable flag, CSV checks nothing at all and behaves like a plain OP_NOP. This is an option left deliberately open for possible future changes through a soft fork.

The history of nSequence and nLockTime
Now that the mechanics are clear, let me open a historical aside, because it sheds light on many of the system’s oddities. The two fields we’ve just seen weren’t designed for the use we make of them today. They were repurposed.
Originally, checking a transaction’s finality was done in a function named IsFinal. A transaction was judged final there, and therefore immediately includable, as soon as one of these two conditions was met:
- its
nLockTimewas 0 or pointed to an instant already past, - or all of its inputs carried an
nSequenceat its maximum value,0xFFFFFFFF.
Since the wallets of the time left nSequence at this maximum value by default, the nLockTime was purely and simply ignored. A transaction could therefore display an absolute timelock while being confirmed on the spot, its coins becoming spendable again right after, as if the timelock didn’t exist.

Traces of this can be found right on the main chain. A transaction whose nLockTime targeted block 198,370, but whose single input had stayed at 0xFFFFFFFF, was mined 11 blocks earlier, at block 198,359. Here is its TXID:
13e100dd08b6da0a7426ea520b0bb3ae54cef79dd045e2e4f7116023df3a5c95

Source mempool.space.
By the way,
nLockTimehasn’t always been a consensus rule. In its early days, it was only a standardness rule. Nodes did refuse to relay or mine a transaction whose deadline hadn’t been reached, but they accepted a block that contained one. In other words, a miner could forcibly include a still-timelocked transaction, and the block remained perfectly valid. Satoshi fixed this with a soft fork. The fix arrived in version 0.1.6 in November 2009, and the rule became binding for blocks from height31,000, reached on December 22, 2009.
To understand this strange behavior, we have to go back to Satoshi’s intent. In the original protocol, a transaction wasn’t a frozen object: it could be replaced by a later version, as long as two conditions allowed it, that its nLockTime hadn’t yet been reached, and that the sequence numbers of its inputs could still increase. The idea is that nSequence served to order successive versions of the same transaction, hence its name “sequence”, and that nLockTime set the deadline after which the latest version became final. A transaction was therefore final if its nLockTime had passed, or if all its inputs were at the maximum, since in that case no version could replace them anymore by increasing the sequence.
On the consensus side, final transactions were allowed to enter a block. On the node-policy side, non-final transactions were also accepted into the mempool, to allow their replacement. Except that this mempool replacement logic was never carried through. Nodes were supposed to keep these non-final transactions until the deadline, or until the arrival of a version with all sequences maxed out, and therefore includable. But no mechanism gave miners an incentive to keep them in memory, and the logic turned out to be irreconcilable with denial-of-service resistance, since it amounted to allowing free and unlimited transaction spam on the network. At the time, the mempool had no size cap, and keeping these replaceable transactions indefinitely weighed heavily on nodes’ memory. The original mechanism was therefore disabled by Satoshi himself in 2010, in Bitcoin version 0.3.12.
What remained was the now-useless nSequence field, and an orphaned consensus rule: “if all inputs are at 0xFFFFFFFF, the transaction is final”. This rule was never removed. Removing it today would require a hard fork, for almost no benefit. This is how nLockTime, originally a replacement deadline, became in effect our absolute timelock: you just have to leave at least one input below 0xFFFFFFFF, typically at 0xFFFFFFFE, for it to recover its full meaning.
As for nSequence, it was recycled twice. First by BIP-0125, which built a new RBF logic. Then by BIP-0068 in 2016, which gave it a new meaning at the consensus level with the relative timelock.
Comparison: absolute vs. relative timelock
In the table below, I offer a final recap comparing these two types of timelock before I tell you more precisely about Liana’s choices on the matter:

Two remarks to round out this overview.
First, you don’t mix units, and the reason is purely structural. nLockTime is a single field, shared by the whole transaction, whereas nSequence exists for each input. A transaction can therefore carry only one absolute timelock value, in a single type of delay, either block height or date. If Alice owned two different coins, one locked by CLTV in block height and the other by CLTV in date, she could never spend them together in a single transaction, for lack of a second nLockTime field. For this reason, we work in block height almost everywhere.
Also, since a block lands on average every 10 minutes, a delay expressed in blocks isn’t a strict time guarantee, it’s an average. One year is about 52,560 blocks, but the real time can vary by a few days depending on the pace of block production. In practice, this isn’t a problem for the long-term uses we care about.
Which type of timelock is used in Liana?
Liana is a Bitcoin wallet based on Miniscript, a framework that lets you cleanly write advanced spending conditions, to combine two types of spending paths on a single wallet:
- A primary path: one that spends immediately, with no time condition, for everyday management.
- One or more recovery paths: conditions that only become active after a period of inactivity. This is the user’s fallback. If they lose access to their main spending path, or if they die, a backup key, a path with different conditions, takes over once the delay has elapsed.

The question then is: to measure a period of inactivity, do you need a relative timelock or an absolute timelock?
A period of inactivity is exactly a relative timelock
What does “inactivity” mean? Alice wants her backup key to activate only if her bitcoins haven’t moved for a year. As long as she moves her coins from time to time, the recovery path stays closed. The day nothing moves anymore, the countdown runs all the way down.
This is exactly the hourglass principle. With a relative timelock, each coin starts its own one-year countdown from its confirmation. As soon as Alice uses her wallet, even just by sending her funds back to herself, she creates new UTXOs and flips all the hourglasses: the recovery path never activates. This is what we call “refreshing” the timelock. The day Alice loses her main key, or is no longer around to sign, no coin moves anymore, the hourglasses run out, and for example a year later she or her heirs recover the funds through the recovery path.
Why not an absolute timelock?
An absolute timelock sets a date once and for all, when the script is created. It knows nothing of Alice’s activity, only the deadline it was given. To write “one year after the last activity”, you’d have to know the date of that last activity at the moment of carving the condition, and no one knows it. The best Alice can do is hard-code a date. And that’s where everything gets complicated.
First, which date to choose? You never know when the owner will pass away, nor when a key will be lost. A very distant date, say 40 years out, guarantees that the recovery path won’t open too early, but if Alice dies tomorrow, her heirs will wait 40 years before touching funds they may need right away. A near date, say next year, handles that case but arrives quickly and forces you to start over endlessly. There’s no good fixed date, precisely because the event we’re trying to cover is unpredictable. A short inactivity delay, refreshed regularly, makes far more sense, and that’s exactly what the relative timelock does.
Next, the protection isn’t uniform with an absolute timelock. If Alice receives a payment on December 30, 2031 and the deadline falls on January 1, 2032, that coin is protected for only two days, whereas a coin received three years earlier is protected for years. The delay no longer means anything, since it’s counted toward a common date and not from each coin’s arrival. The relative timelock, by contrast, gives each coin the same full delay from its own receipt, whether it arrives today or in five years.

Finally, maintaining an absolute timelock is cumbersome and risky. Refreshing a relative timelock costs almost nothing: Alice moves her funds to one of her addresses, the countdown restarts, and the descriptor never changes. The same script serves indefinitely. Pushing back an absolute deadline, by contrast, means building a new script, hence a new descriptor, hence a new backup, and starting over at each deadline. You then stack up successive wallets that you can’t even disable, because Bitcoin offers no way to disable an old wallet. That’s where the trouble can start: you accidentally reuse an address from an old wallet, you miss a descriptor backup, you damage your privacy by reusing xpubs, and so on. Every script change is an opportunity to make a mistake, where a single script offers none.
This doesn’t mean the absolute timelock is useless, nor that Liana rules out ever touching it. Future versions could very well offer features built on it. But that would then require significant user-experience work to neutralize all the traps we’ve just seen, and that work remains to be done.
You also have to clearly understand that, in our use case, the absolute timelock’s only advantage over the relative timelock lies not in how it works, but in the duration it can reach. This is why a possible widening of the values available for the relative timelock would offer the best of both worlds, and discussions to that effect are already underway.

TL;DR
A timelock doesn’t freeze your bitcoins. It writes a time condition into a coin’s spending logic, and the entire network enforces it.
There are two types of timelock. The absolute timelock is like a calendar: it points to a fixed instant, via nLockTime and the CLTV opcode. The relative timelock is like an hourglass: it counts a delay from the coin’s confirmation, via nSequence and the CSV opcode, and it resets each time the coin moves.
This reset property is exactly what’s needed to measure inactivity. That’s why Liana uses only relative timelocks for now.
If you want to see what a wallet built on relative timelocks looks like, you can try Liana at lianawallet.com. And to go further, I recommend this practical article in which I show you how to turn a Coldcard into a key able only to refresh a timelock, never to spend the funds: Create a refresh-only key for your timelocks with Coldcard SSSP.