- 2201.12.10 (Swan Lake Update 12)
- 2201.12.9 (Swan Lake Update 12)
- 2201.12.8 (Swan Lake Update 12)
- 2201.12.7 (Swan Lake Update 12)
- 2201.12.6 (Swan Lake Update 12)
- 2201.12.5 (Swan Lake Update 12)
- 2201.12.4 (Swan Lake Update 12)
- 2201.12.3 (Swan Lake Update 12)
- 2201.12.2 (Swan Lake Update 12)
- 2201.12.1 (Swan Lake Update 12)
- 2201.12.0 (Swan Lake Update 12)
- 2201.8.10 (Swan Lake Update 8)
- 2201.8.9 (Swan Lake Update 8)
- 2201.8.8 (Swan Lake Update 8)
- 2201.8.7 (Swan Lake Update 8)
- 2201.8.6 (Swan Lake Update 8)
- 2201.8.5 (Swan Lake Update 8)
- 2201.8.4 (Swan Lake Update 8)
- 2201.8.3 (Swan Lake Update 8)
- 2201.8.2 (Swan Lake Update 8)
- 2201.8.1 (Swan Lake Update 8)
- 2201.8.0 (Swan Lake Update 8)
- 1.2.62
- 1.2.61
- 1.2.60
- 1.2.59
- 1.2.58
- 1.2.57
- 1.2.56
- 1.2.55
- 1.2.54
- 1.2.53
- 1.2.52
- 1.2.51
- 1.2.50
- 1.2.49
- 1.2.48
- 1.2.47
- 1.2.46
- 1.2.45
- 1.2.44
- 1.2.43
- 1.2.42
- 1.2.41
- 1.2.40
- 1.2.39
- 1.2.38
- 1.2.37
- 1.2.36
- 1.2.35
- 1.2.34
- 1.2.33
- 1.2.32
- 1.2.31
- 1.2.30
- 1.2.29
- 1.2.28
- 1.2.27
- 1.2.26
- 1.2.25
- 1.2.24
- 1.2.23
- 1.2.22
- 1.2.21
- 1.2.20
- 1.2.19
- 1.2.18
- 1.2.17
- 1.2.16
- 1.2.15
- 1.2.14
- 1.2.13
- 1.2.12
- 1.2.11
- 1.2.10
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
Overview of Ballerina Swan Lake Update 13 (2201.13.0)
Swan Lake Update 13 (2201.13.0) is the thirteenth update release of Ballerina Swan Lake, and it includes a new set of features and significant improvements to the compiler, runtime, Ballerina library, and developer tooling. It is based on the 2024R1 version of the Language Specification.
Update Ballerina
Update your current Ballerina installation directly to 2201.13.0 using the Ballerina Update Tool as follows.
- Run
bal updateto get the latest version of the Update Tool. - Run
bal dist updateto update to this latest distribution.
Install Ballerina
If you have not installed Ballerina, download the installers to install.
Language updates
New features
Natural expressions
Natural expressions have been introduced as experimental first-class syntax for natural language integrations. Natural expressions are blocks of natural language instructions that are executed at runtime with the help of a generator capable of understanding/executing the instructions in natural language (e.g., a generative AI model such as a large language model (LLM)). They are dependently typed, allowing generators to identify the required result format and bind the response to the expected type.
import ballerina/ai; import ballerina/io; // Use the default model provider (with configuration added via a Ballerina VS Code command). // Alternatively, to use your own keys, use the relevant `ballerinax/ai.<provider>` (e.g., // `ballerinax/ai.openai`, `ballerinax/ai.anthropic`, etc.) model provider implementation. final ai:ModelProvider model = check ai:getDefaultModelProvider(); // Define a type corresponding to the response you expect from the LLM. type Joke record {| string setup; string punchline; |}; function generateJoke(string subject) returns Joke|error { // Use a natural expression with instruction specified in natural language. // The expected type (`Joke`) is used to automatically generate the schema to // be included in the request to the model. The relevant parts of the response // are then extracted and parsed as a `Joke` value. // A natural expression may evaluate to an `error` if the request or parsing fails. Joke|error joke = // The `natural` expression allows specifying natural language instructions directly. natural (model) { Tell me a joke about ${subject}! Make it suitable for all audiences. }; return joke; } public function main() returns error? { Joke jokeResponse = check generateJoke("programming"); io:println("Setup: ", jokeResponse.setup); io:println("Punchline: ", jokeResponse.punchline); }
Natural expressions can be multimodal; the model provider implementations handle insertions of document types such as ai:ImageDocument, ai:AudioDocument, and ai:FileDocument to transform them into the multimodal request format expected by the LLM API.
import ballerina/ai; import ballerina/io; final ai:ModelProvider model = check ai:getDefaultModelProvider(); public function main() returns error? { // Define an `ai:ImageDocument` value with a URL to an image. ai:ImageDocument image = { content: "https://ballerina.io/img/branding/ballerina_logo_dgrey_png.png" }; // Include the image document as an insertion (`${...}`) in the natural expression. // The model provider will detect the multimodal input and handle // constructing the request appropriately. string? description = check natural (model) { Describe this image. ${image} If it is not possible to describe the image, respond with null. }; io:println(description); }
Note: These examples use the default model provider. To generate the necessary configuration, open up the VS Code command palette (
Ctrl+Shift+Porcommand+shift+P), and run theConfigure default WSO2 Model Providercommand to add your configuration to theConfig.tomlfile. If not already logged in, log in to the Ballerina Copilot when prompted. Alternatively, to use your own keys, use the relevantballerinax/ai.<provider>model provider implementation.
Note: This is currently an experimental feature and requires the
--experimentalflag to be used withbalcommands.
For more information, see Natural Language is Code: A hybrid approach with Natural Programming and Work with Large Language Models (LLMs) using natural expressions.
Compile-time code generation
Experimental support for compile-time code generation has also been introduced as a part of Natural Programming. This allows users to describe what data (e.g., test data) should look like or what the implementation of a function should be in natural language in the source code, and have the data or implementation be generated at compile time with the help of a generative AI model. Inspired by literate programming, this allows for more expressive source code.
Compile-time code generation is of two variants.
-
Data generation -
const naturalexpressionsA
const naturalexpression can be used to generate data (i.e., values that belong toanydata).import ballerina/test; type Employee record {| int id; string name; string department; decimal salary; |}; function filterEmployees(Employee[] employees, string department, decimal salary) returns Employee[] => from Employee emp in employees where emp.department == department && emp.salary > salary select emp; @test:Config function testFilterEmployees() { // Use a const natural expression to generate a dataset of employees. Employee[] employees = const natural { Generate data sets of employees with varying departments and salaries to test a function that filters employees belonging to a specific department and earning above a certain salary threshold. Use legal, finance, and tech departments with salaries ranging from 50000 to 150000. }; // Define the department and salary threshold for filtering, either as hardcoded values // or using `const natural` expressions. string department = const natural { Select a department from legal, finance, and tech.}; decimal salaryThreshold = const natural { Select a salary threshold between 50000 and 150000. }; Employee[] filteredEmployees = filterEmployees(employees, department, salaryThreshold); int currIndex = 0; int filteredEmployeesLength = filteredEmployees.length(); foreach Employee employee in filteredEmployees { if employee.department == department && employee.salary > salaryThreshold { test:assertTrue(currIndex < filteredEmployeesLength); test:assertExactEquals(filteredEmployees[currIndex], employee); currIndex += 1; } } test:assertEquals(currIndex, filteredEmployeesLength); } -
Function generation -
@natural:code externalfunctionsAn
externalfunction can be annotated with@natural:codewith thepromptfield describing the implementation of the function. Note that this is only allowed with projects (and not in single file mode) and the code generated for the function is persisted in thegenerateddirectory. Since there is no developer in the loop to review and approve the generated code during the build, some restrictions (such as limiting the organizations from which modules can be imported) have been introduced, compared to a Copilot.type Employee record {| int id; string name; string department; decimal salary; |}; function filterEmployees(Employee[] employees, string department, decimal salary) returns Employee[] = @natural:code { prompt: string `Filter employees who belong to the specified department and have a salary greater than the given threshold.` } external;Note that this currently works with the Ballerina Copilot configuration. To generate the configuration, open up the VS Code command palette (
Ctrl+Shift+Porcommand+shift+P), and run theConfigure default WSO2 Model Providercommand to add your configuration to theConfig.tomlfile. If not already logged in, log in to the Ballerina Copilot when prompted. Use these values as theBAL_CODEGEN_URLandBAL_CODEGEN_TOKENenvironment variables for compile-time code generation.
OpenShift support
Ballerina code to cloud plugin now supports generation of OpenShift artifacts. The artifacts can be generated using the following command:
$ bal build --cloud=openshift
The following OpenShift artifacts will be generated in the target directory.
DeploymentServiceHorizontal Pod Autoscaler
Users can use the generated artifacts to deploy the Ballerina service in an OpenShift cluster. The commands printed in the console can be used to deploy the service.
$ bal build --cloud=openshift Compiling source wso2/hello_openshift:0.1.0 Generating executable Generating artifacts... @kubernetes:Service - complete 2/2 @kubernetes:ConfigMap - complete 1/1 @kubernetes:Deployment - complete 1/1 @kubernetes:HPA - complete 1/1 @kubernetes:Docker - complete 2/2 Execute the below command to deploy the Kubernetes artifacts: oc apply -f /home/wso2/c2c-guide/hello_openshift/target/openshift/hello_openshift target/bin/hello_openshift.jar
Improvements
Improved XML parsing to support XML declarations
Previously, the xml:fromString() function did not capture XML declaration(<?xml version="1.1" encoding="UTF-8"?>) when converting a string into a xml value. With this update, the XML declaration is now correctly recognized and preserved during parsing.
import ballerina/io; public function main() returns error? { string str = string `<?xml version="1.1" encoding="UTF-8"?><A><B>123</B></A>`; xml xmlVal = check xml:fromString(str); io:println(xmlVal); // prints `<?xml version="1.1" encoding="UTF-8"?><A><B>123</B></A>` }
Ballerina library updates
New features
time package
Added support for add/subtract specified durations to/from time values.
import ballerina/io; import ballerina/time; public function main() { // Add a time duration to the given time value by first converting it to a civil value and using the civilAddDuration function. time:Civil civil = check time:civilFromString("2025-04-13T17:35:30.120Z"); civil = check time:civilAddDuration(civil, {years: 1, months: 3, days: 5, hours: 6, minutes: 9, seconds: 1}); io:println(check time:civilToString(civil)); // Prints "2026-07-18T23:44:31.120Z" // Add a time duration to the specified time value by first converting it to a civil value and using the civilAddDuration function, taking the given time zone into account. time:TimeZone timeZone = check new("Asia/Colombo"); civil = check time:civilFromString("2025-04-13T17:35:30.120-08:00[America/Los_Angeles]"); civil = check timeZone.civilAddDuration(civil, {years: 1, months: 3, days: 5, hours: 6, minutes: 9, seconds: 1}); io:println(check time:civilToString(civil)); // 2026-07-19T13:14:31.120+05:30[Asia/Colombo] }
Improvements
oauth2 package
Added support for configuring the connection and request timeouts for the internal HTTP client.
ClientCredentialsGrantConfig config = { // ... other configurations clientConfig: { connectTimeout: 30, reqTimeout: 60 } };
Developer tools updates
New features
CLI
Decoupled CLI tools from the distribution
Support for independent CLI tool releases has been introduced, allowing commonly used Ballerina CLI tools (bal openapi, bal graphql, bal grpc, bal persist) to be updated independently from the main Ballerina distribution. This enhancement enables faster delivery of bug fixes and new features for tools without requiring a full distribution release.
Below is an example on how to update the openapi tool to the latest version compatible with the current distribution.
$ bal tool update openapi
Improvements
Introduced the --dependency-cache flag to bal clean command. This cleans the caches of the dependencies of a package in addition to the cache of the user's package.
$ bal clean --dependency-cache
Ballerina packages updates
New features
Introduced multi-package workspace support
Multi-package workspace support has been introduced to enable developers to organize and manage multiple interdependent Ballerina packages within a single workspace in a monorepo-style structure. Dependencies within the workspace packages are resolved seamlessly without needing to publish to a package repository.
Below is an example of a multi-package workspace structure:
my-workspace/ ├── Ballerina.toml # Workspace configuration ├── order-service/ │ ├── Ballerina.toml # Package configuration │ └── service.bal ├── menu-service/ │ ├── Ballerina.toml │ └── service.bal └── utils/ ├── Ballerina.toml └── utils.bal
The workspace-level Ballerina.toml file defines the workspace configuration with the packages to include in the workspace:
[workspace] packages = ["order-service", "menu-service", "utils"]
To create a new workspace, use bal new --workspace <workspace-name>, which creates the workspace configuration with a sample project. Core commands such as bal build, bal run, bal test, and bal pack are also enhanced to support workspaces.
For more information, see the Workspaces documentation.
Improvements
Improved the compilation time of consecutive builds
Previously, every invocation of bal build followed by bal run would recompile the entire project from scratch, even when no changes were made to the source files since the last build. With this update, the build system now detects unchanged projects and skips redundant compilation steps after the first build run within the next 24 hours.
The example below shows the output when sources are up to date:
Compiling source (UP-TO-DATE) myorg/hello_app:0.1.0 Generating executable (UP-TO-DATE) myorg/target/bin/hello_app.jar
Running bal clean will delete the caches and force a full recompilation on the next build.
Bug fixes
To view all the bug fixes related to the compiler, runtime, and developer tools, see the GitHub milestone for Swan Lake Update 13 (2201.13.0) for Ballerina platform.
To view all the bug fixes related to the Ballerina library, see the GitHub milestone for Swan Lake Update 13 (2201.13.0) for Ballerina Library.