diff --git a/core/src/main/java/com/graphhopper/GraphHopper.java b/core/src/main/java/com/graphhopper/GraphHopper.java
index 7a700f7dc..46a0b6f08 100644
--- a/core/src/main/java/com/graphhopper/GraphHopper.java
+++ b/core/src/main/java/com/graphhopper/GraphHopper.java
@@ -22,6 +22,7 @@ import com.graphhopper.config.LMProfile;
 import com.graphhopper.config.Profile;
 import com.graphhopper.reader.dem.*;
 import com.graphhopper.reader.osm.OSMReader;
+import com.graphhopper.reader.osm.OSMReaderOSM;
 import com.graphhopper.reader.osm.conditional.DateRangeParser;
 import com.graphhopper.routing.DefaultWeightingFactory;
 import com.graphhopper.routing.Router;
@@ -644,7 +645,7 @@ public class GraphHopper implements GraphHopperAPI {
                     + " but also cannot use file for DataReader as it wasn't specified!");
 
         logger.info("start creating graph from " + osmFile);
-        OSMReader reader = new OSMReader(ghStorage).setFile(_getOSMFile()).
+        OSMReader reader = new OSMReaderOSM(ghStorage).setFile(_getOSMFile()).
                 setElevationProvider(eleProvider).
                 setWorkerThreads(dataReaderWorkerThreads).
                 setWayPointMaxDistance(dataReaderWayPointMaxDistance).
diff --git a/core/src/main/java/com/graphhopper/OSMGraphHopper.java b/core/src/main/java/com/graphhopper/OSMGraphHopper.java
new file mode 100644
index 000000000..4db9b0d11
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/OSMGraphHopper.java
@@ -0,0 +1,59 @@
+package com.graphhopper;
+
+import com.graphhopper.storage.DataAccess;
+import com.graphhopper.storage.Directory;
+import com.graphhopper.util.BitUtil;
+import com.graphhopper.util.JsonFeatureCollection;
+
+public class OSMGraphHopper extends GraphHopper {
+
+    private DataAccess edgeMapping;
+    private DataAccess nodeMapping;
+    private BitUtil bitUtil;
+    private Directory dir;
+
+    public OSMGraphHopper() {
+        this(null);
+    }
+
+    public OSMGraphHopper(JsonFeatureCollection landmarkSplittingFeatureCollection) {
+        super(landmarkSplittingFeatureCollection);
+    }
+
+    @Override
+    public boolean load(String graphHopperFolder) {
+        boolean loaded = super.load(graphHopperFolder);
+        dir = getGraphHopperStorage().getDirectory();
+        bitUtil = BitUtil.get(dir.getByteOrder());
+        edgeMapping = dir.find("edge_mapping");
+        nodeMapping = dir.find("node_mapping");
+
+        if(loaded) {
+            edgeMapping.loadExisting();
+            nodeMapping.loadExisting();
+        }
+
+        return loaded;
+    }
+
+    @Override
+    protected void flush() {
+        super.flush();
+        edgeMapping.flush();
+        nodeMapping.flush();
+    }
+
+    public long getOSMWay(int internalEdgeId) {
+        long pointer = 8L * internalEdgeId;
+        return bitUtil.combineIntsToLong(edgeMapping.getInt(pointer), edgeMapping.getInt(pointer + 4L));
+    }
+
+    public long getOSMNode(int internalNodeId) {
+        if(internalNodeId >= getGraphHopperStorage().getNodes()) {
+            return -1;
+        }
+        long pointer = 8L * internalNodeId;
+        long res = bitUtil.combineIntsToLong(nodeMapping.getInt(pointer), nodeMapping.getInt(pointer + 4L));
+        return res;
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/OSMReaderOSM.java b/core/src/main/java/com/graphhopper/reader/osm/OSMReaderOSM.java
new file mode 100644
index 000000000..6688e08f5
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/OSMReaderOSM.java
@@ -0,0 +1,67 @@
+package com.graphhopper.reader.osm;
+
+import com.graphhopper.reader.ReaderNode;
+import com.graphhopper.storage.DataAccess;
+import com.graphhopper.storage.Directory;
+import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.util.BitUtil;
+
+public class OSMReaderOSM extends OSMReader {
+    private static final BitUtil bitUtil = BitUtil.LITTLE;
+    private final DataAccess towerNodeMapping;
+    private final DataAccess pillarNodeMapping;
+    private final DataAccess edgeMapping;
+
+    public OSMReaderOSM(GraphHopperStorage ghStorage) {
+        super(ghStorage);
+        Directory dir = ghStorage.getDirectory();
+        towerNodeMapping = dir.find("tower_node_mapping");
+        towerNodeMapping.create(2000);
+        pillarNodeMapping = dir.find("pillar_node_mapping");
+        pillarNodeMapping.create(2000);
+        edgeMapping = dir.find("edge_mapping");
+        edgeMapping.create(1000);
+    }
+
+    @Override
+    boolean addNode(ReaderNode node) {
+        boolean result = super.addNode(node);
+
+        if (result) {
+            int internalNodeId = this.getNodeMap().get(node.getId());
+            storeOsmNodeID(internalNodeId, node.getId());
+        }
+        return result;
+    }
+
+    protected void storeOsmNodeID(int nodeId, long osmNodeId) {
+        final DataAccess nodeMapping;
+        if (nodeId < 0) {
+            // if nodeId < 0 then this is a tower node
+            nodeId = -nodeId;
+            nodeMapping = towerNodeMapping;
+        } else {
+            // if nodeId > 0 then this is a pillar node
+            nodeMapping = pillarNodeMapping;
+        }
+        // Not sure why the node process adds 3 to the node id?
+        // Possibly as tower and pillar node are internally stored in the same map,
+        // The +3 removes the conflict where id == 0, which would result in tower == -0, pillar == 0
+        nodeId -= 3;
+        long pointer = 8L * nodeId;
+        nodeMapping.ensureCapacity(pointer + 8L);
+        nodeMapping.setInt(pointer, bitUtil.getIntLow(osmNodeId));
+        nodeMapping.setInt(pointer + 4, bitUtil.getIntHigh(osmNodeId));
+    }
+
+    @Override
+    protected void storeOsmWayID(int edgeId, long osmWayId) {
+        super.storeOsmWayID(edgeId, osmWayId);
+
+        long pointer = 8L * edgeId;
+        edgeMapping.ensureCapacity(pointer + 8L);
+
+        edgeMapping.setInt(pointer, bitUtil.getIntLow(osmWayId));
+        edgeMapping.setInt(pointer + 4, bitUtil.getIntHigh(osmWayId));
+    }
+}
diff --git a/web-bundle/src/main/java/com/graphhopper/http/GraphHopperManaged.java b/web-bundle/src/main/java/com/graphhopper/http/GraphHopperManaged.java
index b11e420f4..7d971920d 100644
--- a/web-bundle/src/main/java/com/graphhopper/http/GraphHopperManaged.java
+++ b/web-bundle/src/main/java/com/graphhopper/http/GraphHopperManaged.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
 import com.graphhopper.GraphHopper;
 import com.graphhopper.GraphHopperConfig;
+import com.graphhopper.OSMGraphHopper;
 import com.graphhopper.config.Profile;
 import com.graphhopper.gtfs.GraphHopperGtfs;
 import com.graphhopper.jackson.Jackson;
@@ -69,7 +70,7 @@ public class GraphHopperManaged implements Managed {
         if (configuration.has("gtfs.file")) {
             graphHopper = new GraphHopperGtfs(configuration);
         } else {
-            graphHopper = new GraphHopper(landmarkSplittingFeatureCollection);
+            graphHopper = new OSMGraphHopper(landmarkSplittingFeatureCollection);
         }
         if (!configuration.getString("spatial_rules.location", "").isEmpty()) {
             throw new RuntimeException("spatial_rules.location has been deprecated. Please use spatial_rules.borders_directory instead.");
diff --git a/web/src/main/java/com/graphhopper/http/cli/MatchCommand.java b/web/src/main/java/com/graphhopper/http/cli/MatchCommand.java
index d930048f7..687a486ba 100644
--- a/web/src/main/java/com/graphhopper/http/cli/MatchCommand.java
+++ b/web/src/main/java/com/graphhopper/http/cli/MatchCommand.java
@@ -21,8 +21,10 @@ package com.graphhopper.http.cli;
 import com.fasterxml.jackson.dataformat.xml.XmlMapper;
 import com.graphhopper.GraphHopper;
 import com.graphhopper.GraphHopperConfig;
+import com.graphhopper.OSMGraphHopper;
 import com.graphhopper.ResponsePath;
 import com.graphhopper.http.GraphHopperServerConfiguration;
+import com.graphhopper.matching.EdgeMatch;
 import com.graphhopper.matching.MapMatching;
 import com.graphhopper.matching.MatchResult;
 import com.graphhopper.matching.Observation;
@@ -92,7 +94,7 @@ public class MatchCommand extends ConfiguredCommand<GraphHopperServerConfigurati
     protected void run(Bootstrap<GraphHopperServerConfiguration> bootstrap, Namespace args, GraphHopperServerConfiguration configuration) {
         GraphHopperConfig graphHopperConfiguration = configuration.getGraphHopperConfiguration();
 
-        GraphHopper hopper = new GraphHopper().init(graphHopperConfiguration);
+        GraphHopper hopper = new OSMGraphHopper().init(graphHopperConfiguration);
         hopper.importOrLoad();
 
         PMap hints = new PMap();
@@ -139,6 +141,8 @@ public class MatchCommand extends ConfiguredCommand<GraphHopperServerConfigurati
                     continue;
                 }
 
+                printOsmWayIds(mr, hopper);
+
                 try (BufferedWriter writer = new BufferedWriter(new FileWriter(outFile))) {
                     long time = gpx.trk.get(0).getStartTime()
                             .map(Date::getTime)
@@ -155,4 +159,16 @@ public class MatchCommand extends ConfiguredCommand<GraphHopperServerConfigurati
         System.out.println("gps import took:" + importSW.getSeconds() + "s, match took: " + matchSW.getSeconds());
     }
 
+    public void printOsmWayIds(MatchResult mr, GraphHopper hopper) {
+        OSMGraphHopper graphHopper = (OSMGraphHopper) hopper;
+        for(EdgeMatch match : mr.getEdgeMatches()) {
+            try {
+                int internalEdgeId = match.getEdgeState().getEdge();
+                System.out.println("EdgeID: " + internalEdgeId + ", OSMWayID: " + graphHopper.getOSMWay(internalEdgeId));
+            } catch (Exception e) {
+                System.out.println(e);
+                e.printStackTrace();
+            }
+        }
+    }
 }
