diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
index 5ba9a19fc1bec57f5bd3f45801f2ab846c3b19a5..74f7fc8119cee26e214e36b29dbdc5d926cefa76 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
@@ -46,7 +46,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * The results are written to S3 as map.csv bucket.
  */
-@SuppressWarnings("unused")
 public class HazardResultSliceLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
index d7ece57af667f4fc877c12ec4a8759cd84822399..1d7db3b60f456792d2aa9ea96b98221a6b078cbe 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
@@ -43,7 +43,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  * AWS Lambda function to list all hazard results in the nshmp-hazout S3 bucket
  * that contain a map.csv file.
  */
-@SuppressWarnings("unused")
 public class HazardResultsMetadataLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
index f48d7babebb87882844c5f7dcfe8d41c24163153..ac5925f3eab869984ad50c92b9bde09d3b01ca3c 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
@@ -39,7 +39,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * @see HazardResultSliceLambda
  */
-@SuppressWarnings("unused")
 public class HazardResultsSlicerLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
index 1cd89db28610eb0b868e9673ebd956cc73128b15..712fb6fc69510fc100414f5069edbcce2892dfab 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
@@ -8,7 +8,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum CybershakeSite implements NamedLocation {
 
   /*
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
index 16e84e249d88a21f0fb798b5d0bc1f4c71cd2cdb..9699ecaf03a92b0273da3528b82b5e70fc955e96 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
@@ -7,7 +7,6 @@ import gov.usgs.earthquake.nshmp.geo.LocationList;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpPolygon {
 
   CEUS_CLIP(Data.CEUS_CLIP, "Central & Eastern US Map Extents"),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
index 370ad713fdd5330c95cdcff74ef8219aadf173a1..2455bd64b52c8ea1e98ba93b84f4cb0b1d1b3f0d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
@@ -18,7 +18,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpSite implements NamedLocation {
 
   // TODO move this and other nshmp specific classes to nshmp-haz
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
index 0aba72dce5ca47cc2b92fc9d00c5d4854f82ceea..c28d33560db41ca95acd50fe5e679328a24d75ef 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
@@ -11,7 +11,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NuregSite implements NamedLocation {
 
   CENTRAL_IL(-90.000, 40.000),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
index 73942632e385a63c037ed4738c8d3f850bd5587d..d678f3a50bf0d8f62addb22fb17ad04777a6aa30 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
@@ -1,11 +1,13 @@
 package gov.usgs.earthquake.nshmp.www;
 
+import java.util.Optional;
+
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.HazardService;
-import gov.usgs.earthquake.nshmp.www.services.HazardService.Query;
+import gov.usgs.earthquake.nshmp.www.services.HazardService.QueryParameters;
 
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -69,21 +71,24 @@ public class HazardController {
   @ApiResponse(
       description = "Hazard curves",
       responseCode = "200")
-  @Get(uri = "{?longitude,latitude,vs30}")
+  @Get // (uri = "{?longitude,latitude,vs30}")
   public HttpResponse<String> doGetHazard(
       HttpRequest<?> request,
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @QueryValue @Nullable Double longitude,
+          maximum = "360") @QueryValue @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @QueryValue @Nullable Double latitude,
-      @Schema(required = true) @QueryValue @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
+          maximum = "90") @QueryValue @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @QueryValue @Nullable Optional<Integer> vs30) {
+
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
   }
 
   /**
@@ -107,15 +112,17 @@ public class HazardController {
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @PathVariable @Nullable Double longitude,
+          maximum = "360") @PathVariable @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @PathVariable @Nullable Double latitude,
-      @Schema(required = true) @PathVariable @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
-  }
+          maximum = "90") @PathVariable @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @PathVariable @Nullable Optional<Integer> vs30) {
 
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
+  }
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
deleted file mode 100644
index 2dbafe63bfc3d5feafd33547007231d80f0ff011..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Interface implemented by enum parameters that impose restrictions on other
- * parameter choices.
- */
-@SuppressWarnings("javadoc")
-public interface Constrained {
-  public Constraints constraints();
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
deleted file mode 100644
index 449d3c7b84eaeb1dfcfb235fc02b7b3841f53457..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Marker interface for supported parameter lists and ; individual enums provide
- * concrete implementations.
- */
-public interface Constraints {}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
index 8e6377de3789d8cf5be488836f49993883f7bdb9..271a99e4341a04164a5f85c259336d8f47c128e1 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
@@ -21,7 +21,6 @@ import gov.usgs.earthquake.nshmp.gmm.GmmInput;
 import gov.usgs.earthquake.nshmp.gmm.GmmInput.Field;
 import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 
-@SuppressWarnings("javadoc")
 public final class MetaUtil {
 
   public static <E extends Enum<E>> List<String> enumsToNameList(
@@ -46,10 +45,10 @@ public final class MetaUtil {
       jObj.addProperty("display", src.toString());
       jObj.addProperty("displayorder", src.ordinal());
 
-      if (src instanceof Constrained) {
-        Constrained cSrc = (Constrained) src;
-        jObj.add("supports", context.serialize(cSrc.constraints()));
-      }
+      // if (src instanceof Constrained) {
+      // Constrained cSrc = (Constrained) src;
+      // jObj.add("supports", context.serialize(cSrc.constraints()));
+      // }
 
       return jObj;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
index e8f5a1e85233637ae30eca229c68735449cb4a18..a358619db2cf21c444bd231f70358a4756e4167f 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
@@ -1,22 +1,19 @@
 package gov.usgs.earthquake.nshmp.www.meta;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
-import com.google.gson.annotations.SerializedName;
 
 import gov.usgs.earthquake.nshmp.geo.Coordinates;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 /**
  * Service metadata, parameterization, and constraint strings, in JSON format.
  */
-@SuppressWarnings("javadoc")
 public final class Metadata {
 
   static final String NSHMP_HAZ_URL = "https://code.usgs.gov/ghsc/nshmp/nshmp-haz";
 
-  @SuppressWarnings("unused")
   private static class Default {
 
     final String status;
@@ -32,48 +29,43 @@ public final class Metadata {
       this.status = Status.USAGE.toString();
       this.description = description;
       this.syntax = syntax;
-      this.server = serverData(1, new Timer());
+      this.server = serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
 
-  public static Object serverData(int threads, Timer timer) {
+  public static Object serverData(int threads, Stopwatch timer) {
     return new Server(threads, timer);
   }
 
-  @SuppressWarnings("unused")
   private static class Server {
 
     final int threads;
-    final String servlet;
-    final String calc;
+    final String timer;
+    final String version;
 
-    @SerializedName("nshmp-haz")
-    final Component nshmpHaz = NSHMP_HAZ_COMPONENT;
-
-    Server(int threads, Timer timer) {
+    Server(int threads, Stopwatch timer) {
       this.threads = threads;
-      this.servlet = timer.servletTime();
-      this.calc = timer.calcTime();
+      this.timer = timer.toString();
+      this.version = "TODO where to get version?";
     }
 
-    static Component NSHMP_HAZ_COMPONENT = new Component(
-        NSHMP_HAZ_URL,
-        Versions.NSHMP_HAZ_VERSION);
-
-    static final class Component {
-
-      final String url;
-      final String version;
-
-      Component(String url, String version) {
-        this.url = url;
-        this.version = version;
-      }
-    }
+    // static Component NSHMP_HAZ_COMPONENT = new Component(
+    // NSHMP_HAZ_URL,
+    // Versions.NSHMP_HAZ_VERSION);
+    //
+    // static final class Component {
+    //
+    // final String url;
+    // final String version;
+    //
+    // Component(String url, String version) {
+    // this.url = url;
+    // this.version = version;
+    // }
+    // }
   }
 
-  @SuppressWarnings("unused")
   public static class DefaultParameters {
 
     // final EnumParameter<Edition> edition;
@@ -132,7 +124,6 @@ public final class Metadata {
     return ServletUtil.GSON.toJson(error);
   }
 
-  @SuppressWarnings("unused")
   private static class Error {
 
     final String status = Status.ERROR.toString();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
index a7f7cf8927f62629d03612a223bb725be875402a..2f744fe8631b0191a04d5db8ca49e9232e589208 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
@@ -11,6 +11,7 @@ import java.util.Properties;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.Resources;
 
@@ -27,7 +28,6 @@ import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.DeaggEpsilonController;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpRequest;
@@ -81,7 +81,7 @@ public final class DeaggEpsilonService {
 
       query.checkValues();
       var data = new RequestData(query, query.vs30);
-      var response = process(data, timer, urlHelper);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -108,11 +108,11 @@ public final class DeaggEpsilonService {
 
   private static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
       UrlHelper urlHelper)
       throws InterruptedException, ExecutionException {
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var timer = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
     var deagg = Deaggregation.atImls(hazard, data.imtImls, ServletUtil.CALC_EXECUTOR);
     return new ResultBuilder()
@@ -186,7 +186,7 @@ public final class DeaggEpsilonService {
     }
   }
 
-  static final class RequestData extends HazardService.RequestData {
+  static final class RequestData extends HazardService.RequestDataOld {
     final EnumMap<Imt, Double> imtImls;
     final boolean basin;
 
@@ -242,7 +242,7 @@ public final class DeaggEpsilonService {
 
   static final class ResultBuilder {
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
     Deaggregation deagg;
 
@@ -256,7 +256,7 @@ public final class DeaggEpsilonService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
index d0186a9bd76db5ebb7d64aa2e160a28adfe9c05a..0a7d816d4fcb7a83c9f3f511a0c4199447fb8924 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
@@ -1,5 +1,6 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static gov.usgs.earthquake.nshmp.calc.HazardExport.curvesBySource;
 
@@ -7,9 +8,12 @@ import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
+
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.Site;
@@ -27,10 +31,8 @@ import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
-import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
@@ -76,17 +78,17 @@ public final class HazardService {
    * @param query The query
    * @param urlHelper The URL helper
    */
-  public static HttpResponse<String> handleDoGetHazard(Query query, UrlHelper urlHelper) {
-    try {
-      var timer = ServletUtil.timer();
+  public static HttpResponse<String> handleDoGetHazard(
+      QueryParameters query,
+      UrlHelper urlHelper) {
 
-      if (query.isNull()) {
+    try {
+      if (query.isEmpty()) {
         return handleDoGetUsage(urlHelper);
       }
-
-      query.checkValues();
-      var data = new RequestData(query, query.vs30);
-      var response = process(data, timer, urlHelper);
+      query.checkParameters();
+      var data = new RequestData(query);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -96,16 +98,18 @@ public final class HazardService {
 
   static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
-      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper)
+      throws InterruptedException, ExecutionException {
+
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var stopwatch = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
 
     return new ResultBuilder()
         .hazard(hazard)
         .requestData(data)
-        .timer(timer)
+        .timer(stopwatch)
         .urlHelper(urlHelper)
         .build();
   }
@@ -135,26 +139,38 @@ public final class HazardService {
     }
   }
 
-  public static class Query extends ServiceQueryData {
-    Integer vs30;
+  public static class QueryParameters {
 
-    public Query(Double longitude, Double latitude, Integer vs30) {
-      super(longitude, latitude);
+    Optional<Double> longitude;
+    Optional<Double> latitude;
+    Optional<Integer> vs30;
+
+    public QueryParameters(
+        Optional<Double> longitude,
+        Optional<Double> latitude,
+        Optional<Integer> vs30) {
+
+      this.longitude = longitude;
+      this.latitude = latitude;
       this.vs30 = vs30;
     }
 
-    @Override
-    public boolean isNull() {
-      return super.isNull() && vs30 == null;
+    public boolean isEmpty() {
+      return longitude.isEmpty() && latitude.isEmpty() && vs30.isEmpty();
     }
 
-    @Override
-    public void checkValues() {
-      super.checkValues();
-      WsUtils.checkValue(Key.VS30, vs30);
+    public void checkParameters() {
+      checkParameter(longitude, "longitude");
+      checkParameter(latitude, "latitude");
+      checkParameter(vs30, "vs30");
     }
   }
 
+  private static void checkParameter(Object param, String id) {
+    checkNotNull(param, "Missing parameter: %s", id);
+    // TODO check range here
+  }
+
   /* Service request and model metadata */
   static class RequestMetadata {
 
@@ -186,30 +202,53 @@ public final class HazardService {
     }
   }
 
-  static class RequestData extends ServiceRequestData {
-    final double vs30; // TODO bad bad bad replacement for Vs30 enum
+  static class RequestData {
 
-    RequestData(Query query, double vs30) {
-      super(query);
-      this.vs30 = vs30;
+    final double longitude;
+    final double latitude;
+    final double vs30;
+
+    RequestData(QueryParameters query) {
+      this.longitude = query.longitude.orElseThrow();
+      this.latitude = query.latitude.orElseThrow();
+      this.vs30 = query.vs30.orElseThrow();
     }
   }
 
   private static final class ResponseMetadata {
-    final SourceModel models;
-    final double latitude;
-    final double longitude;
-    final Imt imt;
-    final double vs30;
+    // final SourceModel model;
+    // final double latitude;
+    // final double longitude;
+    // final double vs30;
+    final String imt;
     final String xlabel = "Ground Motion (g)";
     final String ylabel = "Annual Frequency of Exceedence";
 
-    ResponseMetadata(RequestData request, Imt imt) {
-      models = new SourceModel(ServletUtil.model());
-      latitude = request.latitude;
-      longitude = request.longitude;
-      this.imt = imt;
-      vs30 = request.vs30;
+    ResponseMetadata(Imt imt) {
+      // model = new SourceModel(ServletUtil.model());
+      // latitude = data.latitude;
+      // longitude = data.longitude;
+      // vs30 = data.vs30;
+      this.imt = imtShortLabel(imt);
+    }
+  }
+
+  private static String imtShortLabel(Imt imt) {
+    if (imt.equals(Imt.PGA) || imt.equals(Imt.PGV)) {
+      return imt.name();
+    } else if (imt.isSA()) {
+      return imt.period() + " s";
+    }
+    return imt.toString();
+  }
+
+  @Deprecated
+  static class RequestDataOld extends ServiceRequestData {
+    final double vs30;
+
+    RequestDataOld(Query query, double vs30) {
+      super(query);
+      this.vs30 = vs30;
     }
   }
 
@@ -246,14 +285,16 @@ public final class HazardService {
   private static final String TOTAL_KEY = "Total";
 
   private static final class ResultBuilder {
+
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
 
     Map<Imt, Map<SourceType, MutableXySequence>> componentMaps;
     Map<Imt, MutableXySequence> totalMap;
 
     ResultBuilder hazard(Hazard hazardResult) {
+      // TODO necessary??
       checkState(totalMap == null, "Hazard has already been added to this builder");
 
       componentMaps = new EnumMap<>(Imt.class);
@@ -262,10 +303,11 @@ public final class HazardService {
       var typeTotalMaps = curvesBySource(hazardResult);
 
       for (var imt : hazardResult.curves().keySet()) {
-        // total curve
+
+        /* Total curve for IMT. */
         XySequence.addToMap(imt, totalMap, hazardResult.curves().get(imt));
 
-        // component curves
+        /* Source component curves for IMT. */
         var typeTotalMap = typeTotalMaps.get(imt);
         var componentMap = componentMaps.get(imt);
 
@@ -287,7 +329,7 @@ public final class HazardService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
@@ -301,7 +343,7 @@ public final class HazardService {
       var hazards = new ArrayList<HazardResponse>();
 
       for (Imt imt : totalMap.keySet()) {
-        var responseData = new ResponseMetadata(request, imt);
+        var responseData = new ResponseMetadata(imt);
         var curves = new ArrayList<Curve>();
 
         // total curve
@@ -322,4 +364,26 @@ public final class HazardService {
       return new Response<>(Status.SUCCESS, NAME, request, response, urlHelper);
     }
   }
+
+  @Deprecated
+  public static class Query extends ServiceQueryData {
+    Integer vs30;
+
+    public Query(Double longitude, Double latitude, Integer vs30) {
+      super(longitude, latitude);
+      this.vs30 = vs30;
+    }
+
+    @Override
+    public boolean isNull() {
+      return super.isNull() && vs30 == null;
+    }
+
+    @Override
+    public void checkValues() {
+      super.checkValues();
+      WsUtils.checkValue(ServicesUtil.Key.VS30, vs30);
+    }
+  }
+
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
index 0fcd21daa2f4efaae35cd27a764fff7b67c75595..071f31da57f77db510374c9c6c1104a4fafe9153 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
@@ -6,6 +6,7 @@ import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.ListenableFuture;
 
 import gov.usgs.earthquake.nshmp.Maths;
@@ -25,7 +26,6 @@ import gov.usgs.earthquake.nshmp.www.meta.Metadata.DefaultParameters;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 import io.micronaut.http.HttpResponse;
 
@@ -87,7 +87,7 @@ public final class RateService {
 
       query.checkValues();
       var requestData = new RequestData(query);
-      var response = processRequest(service, requestData, urlHelper, timer);
+      var response = processRequest(service, requestData, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -104,8 +104,8 @@ public final class RateService {
   static Response<RequestData, ResponseData> processRequest(
       Service service,
       RequestData data,
-      UrlHelper urlHelper,
-      Timer timer) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+    var timer = Stopwatch.createStarted();
     var rates = calc(service, data);
     var responseData = new ResponseData(new ResponseMetadata(service, data), rates, timer);
     return new Response<>(Status.SUCCESS, service.name, data, responseData, urlHelper);
@@ -259,7 +259,7 @@ public final class RateService {
     final ResponseMetadata metadata;
     final List<Sequence> data;
 
-    ResponseData(ResponseMetadata metadata, EqRate rates, Timer timer) {
+    ResponseData(ResponseMetadata metadata, EqRate rates, Stopwatch timer) {
       server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       this.metadata = metadata;
       this.data = buildSequence(rates);
@@ -319,7 +319,7 @@ public final class RateService {
     private Usage(Service service, DefaultParameters parameters) {
       description = service.description;
       this.syntax = service.syntax;
-      server = Metadata.serverData(1, ServletUtil.timer());
+      server = Metadata.serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
index 3cf5b3470f6fd3269302133d0495327f5b29a895..7efcfbc9826c2b052d9fd038e618804cc3ab6445 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
@@ -17,7 +17,6 @@ import gov.usgs.earthquake.nshmp.internal.www.Response;
 import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
 
@@ -59,7 +58,9 @@ class ServicesUtil {
     return Hazard.merge(hazards);
   }
 
+  @Deprecated
   static class ServiceQueryData implements ServiceQuery {
+
     public final Double longitude;
     public final Double latitude;
 
@@ -80,13 +81,13 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   static class ServiceRequestData {
-    public final SourceModel model;
+
     public final double longitude;
     public final double latitude;
 
     public ServiceRequestData(ServiceQueryData query) {
-      model = new SourceModel(ServletUtil.model());
       longitude = query.longitude;
       latitude = query.latitude;
     }
@@ -118,6 +119,7 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   private static interface ServiceQuery {
     boolean isNull();
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
index ba4284d1c9204de9a232f84783713c9d73ad9b2d..ca44830476be7e89c0aa7dc1d861f3898444dfca 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
@@ -162,6 +162,7 @@ public class ServletUtil {
    * Simple timer object. The servlet timer just runs. The calculation timer can
    * be started later.
    */
+  @Deprecated
   public static final class Timer {
     Stopwatch servlet = Stopwatch.createStarted();
     Stopwatch calc = Stopwatch.createUnstarted();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
index cc74be8809766172bed2120458ceda6cde82ae9d..4773a3c8026e137f9e333301737ec5d87e6f9f56 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
@@ -3,6 +3,7 @@ package gov.usgs.earthquake.nshmp.www.services;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.base.Stopwatch;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 
@@ -66,7 +67,7 @@ public class SourceServices {
 
     public ResponseData() {
       this.description = "Installed source model listing";
-      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, ServletUtil.timer());
+      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, Stopwatch.createStarted());
       // this.parameters = new Parameters();
     }
   }
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
index 6864f0aec64ee546c7cfee39761ab3ca9de852a4..25f4935f56f7b858cfffb487bfe86555c6e1c4e9 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
@@ -44,7 +44,6 @@ package gov.usgs.earthquake.nshmp;
  * @see NshmTestsSmall
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsLarge {
 
   // private static final List<String> COUS_REGION_IDS = ImmutableList.of("wus",
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
index 26dcf4527bdd771a5bcf56e83388c66b3c99e0d6..c85c84aa311babefc937377d80993f59f9de145f 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
@@ -27,7 +27,6 @@ package gov.usgs.earthquake.nshmp;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsSmall {
 
   // /*
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
index 46274746a6c36c931df020a798eeeee54d6769a0..8ffeefca020c785ec60bcc40a02c1ff11e12e95e 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
@@ -3,7 +3,6 @@ package gov.usgs.earthquake.nshmp.programs;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-@SuppressWarnings("javadoc")
 public class HazardCurveTest {
 
   @BeforeEach
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
index 866975eec275b372c8a8ab464c81369fa3762d5b..d6da4edd245eb088762d09055ff7a8054b2a36ab 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
@@ -59,7 +59,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.internal.UsRegion;
 import gov.usgs.earthquake.nshmp.site.NshmpSite.StateComparator;
 
-@SuppressWarnings("javadoc")
 public class NshmpSiteTests {
 
   @Test