diff --git a/config.json b/config.json
index 091feb8..504987c 100644
--- a/config.json
+++ b/config.json
@@ -474,6 +474,14 @@
         "prerequisites": [],
         "difficulty": 2
       },
+      {
+        "slug": "atbash-cipher",
+        "name": "Atbash Cipher",
+        "uuid": "d92ec5ae-e9b1-4089-a633-c885050d679c",
+        "practices": [],
+        "prerequisites": [],
+        "difficulty": 2
+      },
       {
         "slug": "protein-translation",
         "name": "Protein Translation",
diff --git a/exercises/practice/atbash-cipher/.docs/instructions.md b/exercises/practice/atbash-cipher/.docs/instructions.md
new file mode 100644
index 0000000..21ca2ce
--- /dev/null
+++ b/exercises/practice/atbash-cipher/.docs/instructions.md
@@ -0,0 +1,27 @@
+# Instructions
+
+Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.
+
+The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards.
+The first letter is replaced with the last letter, the second with the second-last, and so on.
+
+An Atbash cipher for the Latin alphabet would be as follows:
+
+```text
+Plain:  abcdefghijklmnopqrstuvwxyz
+Cipher: zyxwvutsrqponmlkjihgfedcba
+```
+
+It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher.
+However, this may not have been an issue in the cipher's time.
+
+Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, leaving numbers unchanged, and punctuation is excluded.
+This is to make it harder to guess things based on word boundaries.
+All text will be encoded as lowercase letters.
+
+## Examples
+
+- Encoding `test` gives `gvhg`
+- Encoding `x123 yes` gives `c123b vh`
+- Decoding `gvhg` gives `test`
+- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog`
diff --git a/exercises/practice/atbash-cipher/.meta/config.json b/exercises/practice/atbash-cipher/.meta/config.json
new file mode 100644
index 0000000..8082084
--- /dev/null
+++ b/exercises/practice/atbash-cipher/.meta/config.json
@@ -0,0 +1,19 @@
+{
+  "authors": [
+    "BNAndras"
+  ],
+  "files": {
+    "solution": [
+      "atbash_cipher.bal"
+    ],
+    "test": [
+      "tests/atbash_cipher_test.bal"
+    ],
+    "example": [
+      ".meta/reference/atbash_cipher.bal"
+    ]
+  },
+  "blurb": "Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.",
+  "source": "Wikipedia",
+  "source_url": "https://en.wikipedia.org/wiki/Atbash"
+}
diff --git a/exercises/practice/atbash-cipher/.meta/reference/atbash_cipher.bal b/exercises/practice/atbash-cipher/.meta/reference/atbash_cipher.bal
new file mode 100644
index 0000000..28fb8f4
--- /dev/null
+++ b/exercises/practice/atbash-cipher/.meta/reference/atbash_cipher.bal
@@ -0,0 +1,46 @@
+import ballerina/lang.regexp;
+
+public function encode(string phrase) returns string {
+    string result = "";
+    int chunk_size = 0;
+    foreach string:Char chr in phrase {
+        if isAlphanumeric(chr) {
+            if chunk_size == 5 {
+                result += " ";
+                chunk_size = 0;
+            }
+            
+            result += encodeChar(chr);
+            chunk_size += 1;
+        }
+    }
+
+    return result;
+}
+
+public function decode(string phrase) returns string {
+    string result = "";
+
+    foreach string:Char chr in phrase {
+        if chr != " " {
+            result += encodeChar(chr);
+        }
+    }
+
+    return result;
+}
+
+function encodeChar(string:Char chr) returns string {
+    string lowered = chr.toLowerAscii();
+    int codePoint = lowered.getCodePoint(0);
+    if codePoint >= 97 && codePoint <= 122 {
+        codePoint = 97 + 122 - codePoint;
+    }
+    
+    return checkpanic string:fromCodePointInt(codePoint);
+}
+
+function isAlphanumeric(string:Char chr) returns boolean {
+    string:RegExp r = re `[a-zA-Z0-9]`;
+    return r.find(chr) is regexp:Span;
+}
diff --git a/exercises/practice/atbash-cipher/.meta/tests.toml b/exercises/practice/atbash-cipher/.meta/tests.toml
new file mode 100644
index 0000000..c082d07
--- /dev/null
+++ b/exercises/practice/atbash-cipher/.meta/tests.toml
@@ -0,0 +1,52 @@
+# This is an auto-generated file.
+#
+# Regenerating this file via `configlet sync` will:
+# - Recreate every `description` key/value pair
+# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
+# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
+# - Preserve any other key/value pair
+#
+# As user-added comments (using the # character) will be removed when this file
+# is regenerated, comments can be added via a `comment` key.
+
+[2f47ebe1-eab9-4d6b-b3c6-627562a31c77]
+description = "encode -> encode yes"
+
+[b4ffe781-ea81-4b74-b268-cc58ba21c739]
+description = "encode -> encode no"
+
+[10e48927-24ab-4c4d-9d3f-3067724ace00]
+description = "encode -> encode OMG"
+
+[d59b8bc3-509a-4a9a-834c-6f501b98750b]
+description = "encode -> encode spaces"
+
+[31d44b11-81b7-4a94-8b43-4af6a2449429]
+description = "encode -> encode mindblowingly"
+
+[d503361a-1433-48c0-aae0-d41b5baa33ff]
+description = "encode -> encode numbers"
+
+[79c8a2d5-0772-42d4-b41b-531d0b5da926]
+description = "encode -> encode deep thought"
+
+[9ca13d23-d32a-4967-a1fd-6100b8742bab]
+description = "encode -> encode all the letters"
+
+[bb50e087-7fdf-48e7-9223-284fe7e69851]
+description = "decode -> decode exercism"
+
+[ac021097-cd5d-4717-8907-b0814b9e292c]
+description = "decode -> decode a sentence"
+
+[18729de3-de74-49b8-b68c-025eaf77f851]
+description = "decode -> decode numbers"
+
+[0f30325f-f53b-415d-ad3e-a7a4f63de034]
+description = "decode -> decode all the letters"
+
+[39640287-30c6-4c8c-9bac-9d613d1a5674]
+description = "decode -> decode with too many spaces"
+
+[b34edf13-34c0-49b5-aa21-0768928000d5]
+description = "decode -> decode with no spaces"
diff --git a/exercises/practice/atbash-cipher/Ballerina.toml b/exercises/practice/atbash-cipher/Ballerina.toml
new file mode 100644
index 0000000..c3ae01f
--- /dev/null
+++ b/exercises/practice/atbash-cipher/Ballerina.toml
@@ -0,0 +1,5 @@
+[package]
+org = "ballerina_exercism"
+name = "atbash_cipher"
+version = "0.1.0"
+distribution = "2201.5.0"
diff --git a/exercises/practice/atbash-cipher/Dependencies.toml b/exercises/practice/atbash-cipher/Dependencies.toml
new file mode 100644
index 0000000..e4f8244
--- /dev/null
+++ b/exercises/practice/atbash-cipher/Dependencies.toml
@@ -0,0 +1,49 @@
+# AUTO-GENERATED FILE. DO NOT MODIFY.
+
+# This file is auto-generated by Ballerina for managing dependency versions.
+# It should not be modified by hand.
+
+[ballerina]
+dependencies-toml-version = "2"
+distribution-version = "2201.5.0"
+
+[[package]]
+org = "ballerina"
+name = "jballerina.java"
+version = "0.0.0"
+
+[[package]]
+org = "ballerina"
+name = "lang.regexp"
+version = "0.0.0"
+dependencies = [
+	{org = "ballerina", name = "jballerina.java"}
+]
+modules = [
+	{org = "ballerina", packageName = "lang.regexp", moduleName = "lang.regexp"}
+]
+
+[[package]]
+org = "ballerina"
+name = "test"
+version = "0.0.0"
+scope = "testOnly"
+dependencies = [
+	{org = "ballerina", name = "jballerina.java"}
+]
+modules = [
+	{org = "ballerina", packageName = "test", moduleName = "test"}
+]
+
+[[package]]
+org = "ballerina_exercism"
+name = "atbash_cipher"
+version = "0.1.0"
+dependencies = [
+	{org = "ballerina", name = "lang.regexp"},
+	{org = "ballerina", name = "test"}
+]
+modules = [
+	{org = "ballerina_exercism", packageName = "atbash_cipher", moduleName = "atbash_cipher"}
+]
+
diff --git a/exercises/practice/atbash-cipher/atbash_cipher.bal b/exercises/practice/atbash-cipher/atbash_cipher.bal
new file mode 100644
index 0000000..ce4d1f9
--- /dev/null
+++ b/exercises/practice/atbash-cipher/atbash_cipher.bal
@@ -0,0 +1,7 @@
+public function encode(string phrase) returns string {
+    // TODO: implement this function
+}
+
+public function decode(string phrase) returns string {
+    // TODO: implement this function
+}
diff --git a/exercises/practice/atbash-cipher/tests/atbash_cipher_test.bal b/exercises/practice/atbash-cipher/tests/atbash_cipher_test.bal
new file mode 100644
index 0000000..cf374b5
--- /dev/null
+++ b/exercises/practice/atbash-cipher/tests/atbash_cipher_test.bal
@@ -0,0 +1,126 @@
+import ballerina/test;
+
+@test:Config
+function encodes_yes() {
+    string phrase = "yes";
+    string expected = "bvh";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_no() {
+    string phrase = "no";
+    string expected = "ml";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_OMG() {
+    string phrase = "OMG";
+    string expected = "lnt";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_spaces() {
+    string phrase = "O M G";
+    string expected = "lnt";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_mindblowingly() {
+    string phrase = "mindblowingly";
+    string expected = "nrmwy oldrm tob";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_numbers() {
+    string phrase = "Testing, 1 2 3, testing.";
+    string expected = "gvhgr mt123 gvhgr mt";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+
+function encodes_deep_thought() {
+    string phrase = "Truth is fiction.";
+    string expected = "gifgs rhurx grlm";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function encodes_all_the_letters() {
+    string phrase = "The quick brown fox jumps over the lazy dog.";
+    string expected = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt";
+    test:assertEquals(encode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_exercism() {
+    string phrase = "vcvix rhn";
+    string expected = "exercism";
+    test:assertEquals(decode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_a_sentence() {
+    string phrase = "zmlyh gzxov rhlug vmzhg vkkrm thglm v";
+    string expected = "anobstacleisoftenasteppingstone";
+    test:assertEquals(decode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_numbers() {
+    string phrase = "gvhgr mt123 gvhgr mt";
+    string expected = "testing123testing";
+    test:assertEquals(decode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_all_the_letters() {
+    string phrase = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt";
+    string expected = "thequickbrownfoxjumpsoverthelazydog";
+    test:assertEquals(decode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_with_too_many_spaces() {
+    string phrase = "vc vix    r hn";
+    string expected = "exercism";
+    test:assertEquals(decode(phrase), expected);
+}
+
+@test:Config {
+    enable: false
+}
+function decodes_with_no_spaces() {
+    string phrase = "zmlyhgzxovrhlugvmzhgvkkrmthglmv";
+    string expected = "anobstacleisoftenasteppingstone";
+    test:assertEquals(decode(phrase), expected);
+}