diff --git a/lib/travis/api/v3/constant_resolver.rb b/lib/travis/api/v3/constant_resolver.rb
new file mode 100644
index 00000000..8e3219a9
--- /dev/null
+++ b/lib/travis/api/v3/constant_resolver.rb
@@ -0,0 +1,17 @@
+require 'tool/thread_local'
+
+module Travis::API::V3
+  module ConstantResolver
+    def self.extended(base)
+      base.resolver_cache = Tool::ThreadLocal.new
+      super
+    end
+
+    attr_accessor :resolver_cache
+
+    def [](key)
+      return key unless key.is_a? Symbol
+      resolver_cache[key] ||= const_get(key.to_s.camelize)
+    end
+  end
+end
diff --git a/lib/travis/api/v3/queries.rb b/lib/travis/api/v3/queries.rb
new file mode 100644
index 00000000..8459ec64
--- /dev/null
+++ b/lib/travis/api/v3/queries.rb
@@ -0,0 +1,5 @@
+module Travis::API::V3
+  module Queries
+    extend ConstantResolver
+  end
+end
diff --git a/lib/travis/api/v3/queries/repository.rb b/lib/travis/api/v3/queries/repository.rb
new file mode 100644
index 00000000..fa1e6d35
--- /dev/null
+++ b/lib/travis/api/v3/queries/repository.rb
@@ -0,0 +1,10 @@
+module Travis::API::V3
+  class Queries::Repository < Query
+    params :id
+
+    def find
+      return ::Repository.find_by_id(id) if id
+      raise WrongParams
+    end
+  end
+end
diff --git a/lib/travis/api/v3/query.rb b/lib/travis/api/v3/query.rb
new file mode 100644
index 00000000..8692620d
--- /dev/null
+++ b/lib/travis/api/v3/query.rb
@@ -0,0 +1,14 @@
+module Travis::API::V3
+  class Query
+    def self.params(*list, prefix: nil)
+      prefix ||= name[/[^:]+$/].underscore
+      list.each { |e| class_eval("def #{e}; @params[\"#{prefix}.#{e}\".freeze]; end") }
+    end
+
+    attr_reader :params
+
+    def initialize(params)
+      @params = params
+    end
+  end
+end
diff --git a/lib/travis/api/v3/renderer.rb b/lib/travis/api/v3/renderer.rb
index caad5bad..0bc6b411 100644
--- a/lib/travis/api/v3/renderer.rb
+++ b/lib/travis/api/v3/renderer.rb
@@ -1,12 +1,8 @@
 module Travis::API::V3
   module Renderer
+    extend ConstantResolver
     extend self
 
-    def [](key)
-      return key if key.respond_to? :render
-      const_get(key.to_s.camelize)
-    end
-
     def format_date(date)
       date && date.strftime('%Y-%m-%dT%H:%M:%SZ')
     end
diff --git a/lib/travis/api/v3/service.rb b/lib/travis/api/v3/service.rb
index 35cbbbae..f5b22b82 100644
--- a/lib/travis/api/v3/service.rb
+++ b/lib/travis/api/v3/service.rb
@@ -1,38 +1,15 @@
 module Travis::API::V3
   class Service
-    def self.required_params
-      @required_params ||= []
-    end
-
-    def self.params(*list, optional: false, prefix: nil)
-      @params ||= []
-      list.each do |param|
-        method = param = param.to_s
-        param = "#{prefix}.#{method}" if prefix
-        define_method(method) { params[param] }
-        required_params << param unless optional
-        @params << param
-      end
-      @params
-    end
-
     attr_accessor :access_control, :params
 
     def initialize(access_control, params)
       @access_control = access_control
       @params         = params
+      @queries        = {}
     end
 
-    def required_params?
-      required_params.all? { |param| params.include? param }
-    end
-
-    def required_params
-      self.class.required_params
-    end
-
-    def run_service(name, added_params = {})
-      Services[name].new(access_control, params: params.merge(added_params)).run
+    def query(type)
+      @queries[type] ||= Queries[type].new(params)
     end
   end
 end
diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb
index 7bc77689..83aa0c9f 100644
--- a/lib/travis/api/v3/services.rb
+++ b/lib/travis/api/v3/services.rb
@@ -1,8 +1,5 @@
 module Travis::API::V3
   module Services
-    def self.[](key)
-      return key if key.respond_to? :new
-      const_get(key.to_s.camelize)
-    end
+    extend ConstantResolver
   end
 end
diff --git a/lib/travis/api/v3/services/find_repository.rb b/lib/travis/api/v3/services/find_repository.rb
index 7091a9bb..31466cd1 100644
--- a/lib/travis/api/v3/services/find_repository.rb
+++ b/lib/travis/api/v3/services/find_repository.rb
@@ -1,7 +1,5 @@
 module Travis::API::V3
   class Services::FindRepository < Service
-    params :id, :github_id, :slug, optional: true, prefix: :repository
-
     def run
       raise NotFound, :repository unless repository and access_control.visible? repository
       Result.new(:repository, repository)
@@ -13,10 +11,7 @@ module Travis::API::V3
     end
 
     def find_repository
-      return ::Repository.find_by_id(id)               if id
-      return ::Repository.find_by_github_id(github_id) if github_id
-      return ::Repository.by_slug(slug).first          if slug
-      raise WrongParams
+      query(:repository).find
     end
   end
 end