Vadim Briliantov
10/28/2025, 1:36 PMsuspend functions can only be called from other suspend functions or from a pre-defined entry points (ex: runBlocking)? I found a way to apply this pattern to ANY restriction using context parameters!
The use-case I described in the article: Preventing cloud-only code from being accedently called in on-premises (self-hosted) deployments, and vice versa!
The magic: If someone tries to call a method that touches restricted code (even indirectly, deep down the call chain) — they get an instant compilation error! 🛑 These bugs literally can’t make it to production.
You can apply this approach to many scenarios, for example:
• restricting test-only code
• guarding database operations from side effects
• preventing GDPR-sensitive data from being sent to analytics services
• And whatever you need!
Takes just a few lines of code, and zero compiler knowledge required. Check it out:
https://blog.kotlin-academy.com/stop-bugs-before-they-happen-compile-time-guardrails-with-kotlin-context-parameters-6696fb54c1e8Youssef Shoaib [MOD]
10/28/2025, 2:28 PM@RestrictsSuspension for this. It prevents captures (well, it doesn't, but it prevents calling the restricted methods without you having the context legitimately, as in thru a builder function from your "safe kernel").
This is really one step before monadic regions. If you want a cool Kotlin example of that, see this thread. I've also been working on a compiler plugin that makes this simpler, with the file and state examples linked above now looking like this and this.
I want to eventually have a plugin that does capture checking so that your article can optionally be checked, with only a few annotations needing to be added. It's a large undertaking though.joseph_ivie
10/28/2025, 2:57 PMdave08
10/28/2025, 4:18 PMdata class Stream(..., context(s3UrlRefresher: S3UrlRefreshService) val streamSignedS3Url: String, ...)
to prevent uses of that url without first seeing if expired (in which case that service should refresh it... what do you guys think of such a use?Youssef Shoaib [MOD]
10/28/2025, 5:28 PMclass Stream(private val streamSignedS3Url: String) {
context(expiredChecker: S3ExpiryChecker)
val streamSignedS3Url get() = this.streamSignedS3Url.takeUnless { expiredChecker.isExpired(it) }
}dave08
10/28/2025, 7:39 PMdave08
10/28/2025, 7:40 PMYoussef Shoaib [MOD]
10/28/2025, 7:50 PMdave08
10/29/2025, 5:04 AMVadim Briliantov
10/29/2025, 11:51 AMdave08
10/29/2025, 11:59 AM