diff --git a/src/main/jastadd/flatter/transforms/ServiceChannelTransforms.jadd b/src/main/jastadd/flatter/transforms/ServiceChannelTransforms.jadd
index 9e877c6b270122dd15195414dc340524ad1acc64..3c23272c1f36db83ca03417960e869eb3de12de1 100644
--- a/src/main/jastadd/flatter/transforms/ServiceChannelTransforms.jadd
+++ b/src/main/jastadd/flatter/transforms/ServiceChannelTransforms.jadd
@@ -8,7 +8,7 @@ aspect ServiceChannelTransforms {
 
         Page res = new Page();
         Map<String, PnObject> addedObjects = new HashMap<>();
-        System.out.println("Transforming service transition: " + this.getId());
+        System.out.println("[INFO] Transforming service transition: " + this.getId());
         ServiceTransitionInformation sti = this.getStaticTransitionInformation().asServiceTransitionInformation();
         res.setId(TemplateConstants.CHANNEL_SERVICE_PAGE_PREFIX + "-" + sti.getServiceName());
 
diff --git a/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd b/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
index 36ad739df466307c87a918ef22ddf2944d967bb4..ba14489df2d85d33167877e39324ec590d3432d2 100644
--- a/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
+++ b/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
@@ -9,15 +9,17 @@ aspect ServicePrototypeTransforms {
     }
 
     // apply rule S4
-    syn Page Page.transformPrototypePage() {
+    syn Page Page.transformPrototypePage(int detectedCapacity) {
 
         int serverCapacity = 0;
         String serviceName = this.getServiceName();
         DinerosTransition serviceTransition = null;
 
         for(DinerosTransition dt : petriNet().allDinerosTransitions()){
-            if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
+            if(detectedCapacity == -1 && dt.getStaticTransitionInformation().isServiceTransitionInformation()){
                 serverCapacity = dt.getStaticTransitionInformation().asServiceTransitionInformation().getServerChannel().getCapacity();
+            } else {
+                serverCapacity = detectedCapacity;
             }
             if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
                 if(dt.getStaticTransitionInformation().asServiceTransitionInformation().getServiceName().equals(serviceName)){
diff --git a/src/main/jastadd/flatter/transforms/SignalTransforms.jadd b/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
index f5d7fe3f8590f920e75b3c7e26383f1333041f04..0573d26f95b947fa001cf098e754b8ae3eda6d02 100644
--- a/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
+++ b/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
@@ -48,13 +48,17 @@ aspect SignalTransforms {
 
                 Transition toTrue = net.getTransitionById(TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_TRUE + "-" + l.getName());
                 Transition toFalse = net.getTransitionById(TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_FALSE + "-" + l.getName());
+                System.out.println("toTrue: " + toTrue.getId());
+                System.out.println("toFalse: " + toFalse.getId());
 
                 // create elements for rule I2 & I3
                 RefTransition toTrueRt = PrimitiveTemplates.getReferenceTransition(toTrue);
-                toTrueRt.setId(toTrue.getId() + "REF-" + i + "-" + j);
+                toTrueRt.setId(toTrue.getId() + "-" + t.getId() + "-REF-" + i + "-" + j);
+                System.out.println("Adding ref transition: " + toTrue.getId() + "-" + t.getId() + "-REF-" + i + "-" + j);
+                System.out.println("REF: " + toTrueRt.getRef().getId());
                 res.addObject(toTrueRt);
                 RefTransition toFalseRt = PrimitiveTemplates.getReferenceTransition(toFalse);
-                toFalseRt.setId(toFalse.getId() + "REF-" + i + "-" + j);
+                toFalseRt.setId(toFalse.getId() + "-" + t.getId() + "-REF-" + i + "-" + j);
                 res.addObject(toFalseRt);
                 RefPlace djRefPlace = PrimitiveTemplates.getReferencePlace(pdi);
                 djRefPlace.setId("DJREF-" + i + "-" + j);
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
index c3dd544ba76edc84ec1107e6638e953d73db6369..f06baf7484241b8f040f96c23bd42018d2c395ab 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
@@ -2,6 +2,7 @@ package de.tudresden.inf.st.pnml.flatter;
 
 import de.tudresden.inf.st.pnml.base.constants.PnmlConstants;
 import de.tudresden.inf.st.pnml.flatter.config.ConfigReader;
+import de.tudresden.inf.st.pnml.flatter.graph.ServiceGraph;
 import de.tudresden.inf.st.pnml.flatter.tina.KtzioProxy;
 import de.tudresden.inf.st.pnml.flatter.tina.SiftProxy;
 import de.tudresden.inf.st.pnml.flatter.tina.TinaProxy;
@@ -24,18 +25,23 @@ public class Main {
         String configPath = (args.length > 1) ? args[1] : null;
         String pnmlPath = (args.length > 0) ? args[0] : null;
 
-        if (pnmlPath == null || configPath == null) {
-            System.out.println("No model found on given input path.");
+        if (pnmlPath == null) {
+            System.out.println("[ERROR] No model found on given input path.");
             return;
         }
 
+        if(configPath == null || configPath.equals("")){
+            System.out.println("[WARNING] No config path configured, no model checking will be executed.");
+        }
+
         // parse the global not flatted petri net
-        //pnmlPath = "/home/sebastian/git/dineros/dineros-v2/dineros/pnml-relast-base/src/main/resources/nets/TestNet3.pnml";
-        //configPath = "src/main/config/siftConfig.json";
         PetriNet petriNet = PnmlParser.parsePnml(pnmlPath).get(0);
 
         // [STAGE 1] Resolve service prototype pages
-        TransformationUtils.transformPrototypePagesRecursive(petriNet.getPage(0), null, petriNet);
+        ServiceGraph serviceGraph = new ServiceGraph();
+        serviceGraph.init(petriNet);
+
+        TransformationUtils.transformPrototypePagesRecursive(petriNet.getPage(0), null, petriNet, serviceGraph);
         petriNet.flushAttrAndCollectionCache();
 
         // [STAGE 2] Transform topic transitions
@@ -72,6 +78,7 @@ public class Main {
         petriNet.addPage(signalValuePage);
         petriNet.transformSignalElements(signalValuePage);
         petriNet.flushTreeCache();
+        petriNet.flushAttrAndCollectionCache();
 
         for(DinerosTransition dt : petriNet.allDinerosTransitions()){
             Page dtClausePage = dt.getStaticTransitionInformation().asSignalTransitionInformation()
@@ -122,29 +129,31 @@ public class Main {
 
         // [STAGE 8] Analyze
         // read config for analyzer from file
-        ConfigReader cr = new ConfigReader(configPath);
-        String[] tinaConfig = cr.getTinaConfigParams();
-        String[] siftConfig = cr.getSiftConfigParams();
-
-        // insert into tina
-        if (tinaConfig.length > 1) {
-            System.out.println("[FLATTENER] Inserting into tina.");
-            TinaProxy tinaProxy = new TinaProxy();
-            String tinaTargetPath = homeDirectory + "/temp/tina/" + "tina-result-" + exportId + ".txt";
-            tinaProxy.analyzePetriNet(inhibitorTargetPath, tinaTargetPath, tinaConfig);
-        }
-
-        // insert into sift
-        if (siftConfig.length > 1) {
-            System.out.println("[FLATTENER] Inserting into sift.");
-            SiftProxy siftProxy = new SiftProxy();
-            String siftTargetPath = homeDirectory + "/temp/sift/" + "sift-result-" + exportId + ".ktz";
-            siftProxy.analyzePetriNet(inhibitorTargetPath, siftTargetPath, siftConfig);
-
-            System.out.println("[FLATTENER] Converting with ktzio.");
-            KtzioProxy ktzioProxy = new KtzioProxy();
-            String ktzioPath = homeDirectory + "/temp/sift/" + "sift-result-converted-" + exportId + ".txt";
-            ktzioProxy.convertBinaryToText(siftTargetPath, ktzioPath);
+        if(configPath != null && !configPath.equals("")) {
+            ConfigReader cr = new ConfigReader(configPath);
+            String[] tinaConfig = cr.getTinaConfigParams();
+            String[] siftConfig = cr.getSiftConfigParams();
+
+            // insert into tina
+            if (tinaConfig.length > 1) {
+                System.out.println("[FLATTENER] Inserting into tina.");
+                TinaProxy tinaProxy = new TinaProxy();
+                String tinaTargetPath = homeDirectory + "/temp/tina/" + "tina-result-" + exportId + ".txt";
+                tinaProxy.analyzePetriNet(inhibitorTargetPath, tinaTargetPath, tinaConfig);
+            }
+
+            // insert into sift
+            if (siftConfig.length > 1) {
+                System.out.println("[FLATTENER] Inserting into sift.");
+                SiftProxy siftProxy = new SiftProxy();
+                String siftTargetPath = homeDirectory + "/temp/sift/" + "sift-result-" + exportId + ".ktz";
+                siftProxy.analyzePetriNet(inhibitorTargetPath, siftTargetPath, siftConfig);
+
+                System.out.println("[FLATTENER] Converting with ktzio.");
+                KtzioProxy ktzioProxy = new KtzioProxy();
+                String ktzioPath = homeDirectory + "/temp/sift/" + "sift-result-converted-" + exportId + ".txt";
+                ktzioProxy.convertBinaryToText(siftTargetPath, ktzioPath);
+            }
         }
 
         System.out.println("[FLATTENER] Finished.");
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/graph/ServiceGraph.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/graph/ServiceGraph.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a38e739f92c030a0f601bd1e4dd867792d29281
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/graph/ServiceGraph.java
@@ -0,0 +1,106 @@
+package de.tudresden.inf.st.pnml.flatter.graph;
+
+import de.tudresden.inf.st.pnml.jastadd.model.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ServiceGraph {
+
+    public List<Node> graph;
+
+    public static class Node{
+
+        public String name;
+        public String serviceName;
+        public List<Node> targets;
+        public List<Node> sources;
+
+        public Node(String name, String serviceName, List<Node> targets, List<Node> sources) {
+            this.name = name;
+            this.serviceName = serviceName;
+            this.targets = targets;
+            this.sources = sources;
+        }
+    }
+
+    public List<Node> init(PetriNet petriNet){
+
+        graph = new ArrayList<>();
+
+        // [1] Create a node for each service channel
+        for(DinerosTransition t : petriNet.allDinerosTransitions()){
+            if(t.getStaticTransitionInformation().isServiceTransitionInformation()){
+                graph.add(new Node(t.getId(), t.getStaticTransitionInformation()
+                        .asServiceTransitionInformation().getServiceName(), new ArrayList<>(), new ArrayList<>()));
+            }
+        }
+
+        // [2] Iterate over nodes to build connections
+        for(Node n : graph){
+            for(DinerosTransition t : petriNet.allDinerosTransitions()){
+                if(t.getId().equals(n.name)){
+                    for(ServiceChannel sc : t.getStaticTransitionInformation().asServiceTransitionInformation().getClientChannels()){
+                        for(Node iterNode : graph){
+                            if(!n.name.equals(iterNode.name) &&
+                                    isPnObjectInPageTree(petriNet.getTransitionById(iterNode.name).ContainingPage(), sc.getRequestPlaceId())){
+                                // [3] Build connections
+                                n.sources.add(iterNode);
+                                iterNode.targets.add(n);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return graph;
+    }
+
+    public boolean isPotentiallyCyclic(String serviceName){
+
+        for(Node n : graph){
+            if(n.serviceName.equals(serviceName)){
+                return isPotentiallyCyclicInternal(n, n);
+            }
+        }
+
+        return true;
+    }
+
+    private boolean isPotentiallyCyclicInternal(Node node, Node iterNode){
+
+        for(Node n : iterNode.targets){
+            if(n.name.equals(node.name)){
+                return true;
+            }
+        }
+
+        for(Node n : iterNode.targets){
+            if(isPotentiallyCyclicInternal(node, n)){
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean isPnObjectInPageTree(Page page, String id){
+
+        // bfs
+        for(PnObject po : page.getObjects()){
+            if(po.getId().equals(id)){
+                return true;
+            }
+        }
+
+        for(PnObject po : page.getObjects()){
+            if(po.isPageNode() &&
+                    isPnObjectInPageTree(po.asPage(), id)){
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
index 3e6023e4fa0c5b725bddf810b7d45b825d7d8d85..602d3a05b13f252ff96e6f5f0fdd36578ee6bfe3 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
@@ -18,10 +18,10 @@ public class NdrioProxy extends AbstractTinaProxy{
 
         if(!isWindows){
 
-            if(homeDirectory.contains("pnml-relast-flatter")){
+            if(homeDirectory.contains("pnml-relast-flattener")){
                 ndrioProcessBuilder.command(homeDirectory + "/libs/tina-3.7.0/bin/ndrio", inputPath, outputPath);
             }else{
-                ndrioProcessBuilder.command(homeDirectory + "/pnml-relast-checker/libs/tina-3.7.0/bin/ndrio", inputPath, outputPath);
+                ndrioProcessBuilder.command(homeDirectory + "/pnml-relast-flattener/libs/tina-3.7.0/bin/ndrio", inputPath, outputPath);
             }
         }else{
             logger.error("Windows is currently not supported. Exiting ...");
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
index 297b7b857d8663619ed0f2b20779db17b8c2ab64..508931c285b33333848e1e64e4922d4a1e421539 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
@@ -113,7 +113,7 @@ public class ReferenceFlatter {
         Page topLevelPage = null;
 
         for (Page p : petriNet.allPages()){
-            if(p.ContainingPage() == null){
+            if(p.getId().equals("top")){
                 topLevelPage = p;
             }
         }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
index 9effaf336c68a1d9db1e0cd1d5a9b61606901537..42688199ce3a220411beb51af2bd77fc3b0a5f85 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
@@ -1,5 +1,6 @@
 package de.tudresden.inf.st.pnml.flatter.transform;
 
+import de.tudresden.inf.st.pnml.flatter.graph.ServiceGraph;
 import de.tudresden.inf.st.pnml.jastadd.model.*;
 
 import java.util.HashMap;
@@ -152,11 +153,37 @@ public class TransformationUtils {
         }
     }
 
-    public static void transformPrototypePagesRecursive(Page page, Page parentPage, PetriNet petriNet){
+    private static DinerosTransition getTransitionByServiceName(PetriNet petriNet, String serviceName){
+
+        for(DinerosTransition t : petriNet.allDinerosTransitions()){
+            if(t.getStaticTransitionInformation().isServiceTransitionInformation()){
+                if(t.getStaticTransitionInformation().
+                        asServiceTransitionInformation().getServiceName().equals(serviceName)){
+                    return t;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public static void transformPrototypePagesRecursive(Page page, Page parentPage, PetriNet petriNet, ServiceGraph serviceGraph){
 
         if(page.canTransformPrototypePage()){
-            System.out.println("Transforming page: " + page.getId());
-            Page transformedPage = page.transformPrototypePage();
+            System.out.println("[INFO] Transforming page: " + page.getId());
+
+            Page transformedPage;
+
+            if(serviceGraph.isPotentiallyCyclic(page.getServiceName())){
+                System.out.println("[WARNING] Detected potentially cyclic service call on: " + page.getServiceName());
+                System.out.println("[WARNING] Falling back to user defined thread number for: " + page.getServiceName());
+                transformedPage = page.transformPrototypePage(-1);
+            } else {
+                int numInstances = getTransitionByServiceName(petriNet,
+                        page.getServiceName()).getStaticTransitionInformation().asServiceTransitionInformation().getNumClientChannel();
+                transformedPage = page.transformPrototypePage(numInstances);
+                System.out.println("[INFO] Transforming prototype page: " + page.getServiceName() + " to " + numInstances + " instances.");
+            }
 
             if(parentPage == null){
                 for(int i = 0; i < petriNet.getNumPage(); i++){
@@ -185,7 +212,7 @@ public class TransformationUtils {
         }
 
         for(Page iterPage : subPages){
-            transformPrototypePagesRecursive(iterPage, page, petriNet);
+            transformPrototypePagesRecursive(iterPage, page, petriNet, serviceGraph);
         }
     }