- Up to 120 seconds for a callout.
- Non-blocking execution - no freezing up your UI or server thread.
- Seamless integration with Lightning Components and LWC.
Let's walk through what continuations are, why you need them, and how to implement them step-by-step using a live API demo endpoint that simulates a delay.
What Are Apex Continuations?
Imagine you're at a coffee shop. You place your order (API request) and instead of waiting at the counter (synchronous callout), you go find a comfy seat. When your drink is ready, they call your name (callback method). That's basically how continuations work.
In technical terms, a continuation is an asynchronous callout mechanism in Apex that lets Salesforce park your request, continue processing other things, and then resume when the external call returns.
Sounds magical, right? Let's see it in action.
Why Use Continuations in Salesforce?
If you're thinking, "Why not just use regular Apex callouts?”, here's the kicker: Salesforce enforces strict limits. For synchronous requests, you're capped at 10 seconds for a callout. That's not a lot if you're hitting a sluggish API.
Continuations give you:
Now, let's build it.
Step-by-Step Implementation
We'll use this handy endpoint that simulates a 10-second delay: https://forceshark.com/api/v1/hello-world/continuation-demo?delayMs=10000
Perfect for testing how continuations work without actually needing a slow backend.
Step 1: Create the Apex Continuation Method
Here's where the Apex magic happens. We'll define a controller that makes the callout and registers the callback.
Pro Tip
Make sure the Apex class is marked @AuraEnabled
and you specify continuation=true
.
Here's the code:
public with sharing class ContinuationDemoController {
@AuraEnabled(cacheable=false continuation=true)
public static Object startContinuation() {
Continuation con = new Continuation(40); // 40-second timeout
con.continuationMethod = 'processResponse';
HttpRequest req = new HttpRequest();
req.setEndpoint('https://forceshark.com/api/v1/hello-world/continuation-demo?delayMs=10000');
req.setMethod('GET');
con.addHttpRequest(req);
return con;
}
@AuraEnabled(cacheable=false)
public static String processResponse(List<String> labels, Object state) {
HttpResponse response = Continuation.getResponse(labels[0]);
return response.getBody();
}
}
Let's break it down:
-
startContinuation()
sets up the continuation and registersprocessResponse()
as the callback. -
processResponse()
receives the HTTP response and returns the body.
Boom - just like ordering your coffee and waiting for the barista to call your name.
Step 2: Call the Continuation from LWC
Next, let's hook this into a Lightning Web Component. You're not calling the endpoint directly from LWC - remember, Salesforce is very protective about callouts from client-side JavaScript. So the LWC will talk to Apex, and Apex handles the callout.
Here's the JS file:
import { LightningElement } from 'lwc';
import startContinuation from '@salesforce/apex/ContinuationDemoController.startContinuation';
export default class ContinuationDemo extends LightningElement {
response;
isLoading = false;
handleStartContinuation() {
this.isLoading = true;
startContinuation()
.then(result => {
this.response = result;
this.isLoading = false;
})
.catch(error => {
console.error(error);
this.isLoading = false;
});
}
}
Quick walkthrough:
-
When the button is clicked,
handleStartContinuation()
fires. - It calls the Apex method and waits for the callback response.
- While it's waiting, we show a "loading"message - no frozen UI here!
Step 3: Add the HTML Template
Let's create the front-end part of our component. It's simple, clean, and gives you real-time feedback while the callout is in progress.
<template>
<lightning-button
label="Start Continuation"
onclick={handleStartContinuation}
disabled={isLoading}>
</lightning-button>
<div if:true={isLoading}>
Waiting for API response (this won't freeze the UI!)...
</div>
<div if:true={response}>
API Response: {response}
</div>
</template>
What's happening here:
- The button triggers the continuation.
-
While
isLoading
is true, it shows a "waiting"message. - Once the response comes back, it gets displayed below.
Simple, right? The user clicks a button, Apex does the heavy lifting, and the UI stays smooth.
Common Gotchas (and How to Avoid Them)
Every Salesforce dev knows that nothing ever works perfectly the first time. So here are a few pitfalls you might hit - and how to dodge them:
Object
for the continuation, and your callback must return something serializable (like a String or JSON).@AuraEnabled(cacheable=true)
with continuations. They're dynamic and don't play well with caching.Bonus Tip: What If You Need to Handle Multiple Requests?
Salesforce allows you to add up to three callouts in a single continuation. Here's a little tweak to the original method if you want to call multiple APIs and wait for all of them to return.
Continuation con = new Continuation(40);
con.continuationMethod = 'processResponse';
HttpRequest req1 = new HttpRequest();
req1.setEndpoint('https://forceshark.com/api/v1/hello-world/continuation-demo?delayMs=10000');
req1.setMethod('GET');
HttpRequest req2 = new HttpRequest();
req2.setEndpoint('https://another-api.com/endpoint');
req2.setMethod('GET');
con.addHttpRequest(req1);
con.addHttpRequest(req2);
Then in your callback:
public static String processResponse(List<String> labels, Object state) {
HttpResponse res1 = Continuation.getResponse(labels[0]);
HttpResponse res2 = Continuation.getResponse(labels[1]);
return 'Res1: ' + res1.getBody() + ', Res2: ' + res2.getBody();
}
When Should You Use Continuations?
Here's a litmus test:
- Long-running APIs (e.g., payments, external search services)
- Third-party integrations with known delays
- You want to avoid governor limits on sync callouts
- Super-quick APIs (under 10 seconds)? Regular callouts are fine.
Wrapping Up
Continuations in Salesforce are like a backstage pass for Apex callouts - they let you dodge strict limits and play nicely with long-running APIs. You get smooth, asynchronous behavior in your LWC, and your users never feel the wait.
By using Apex continuations alongside LWC, you're building scalable, performant, and user-friendly apps that handle real-world delays like a champ.
Next time your API takes a coffee break, let continuations do the waiting.
Ready to give your Apex callouts a speed boost? Go try it out with the demo endpoint, and watch your Lightning Web Components shine!